mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-29 18:28:11 +00:00
General work on the Dynamips backend (need to finish and polish).
This commit is contained in:
parent
2516bf80a8
commit
cef29e53aa
@ -2,4 +2,4 @@ GNS3-server
|
|||||||
===========
|
===========
|
||||||
|
|
||||||
GNS3 server manages emulators such as Dynamips, VirtualBox or Qemu/KVM.
|
GNS3 server manages emulators such as Dynamips, VirtualBox or Qemu/KVM.
|
||||||
Clients like the GNS3 GUI controls the server using an API over Websockets.
|
Clients like the GNS3 GUI controls the server using a JSON-RPC API over Websockets.
|
||||||
|
@ -23,7 +23,7 @@ import zmq
|
|||||||
import uuid
|
import uuid
|
||||||
import tornado.websocket
|
import tornado.websocket
|
||||||
from tornado.escape import json_decode
|
from tornado.escape import json_decode
|
||||||
from ..jsonrpc import JSONRPCParseError, JSONRPCInvalidRequest, JSONRPCMethodNotFound
|
from ..jsonrpc import JSONRPCParseError, JSONRPCInvalidRequest, JSONRPCMethodNotFound, JSONRPCNotification
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -59,7 +59,7 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
return self._session_id
|
return self._session_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dispatch_message(cls, message):
|
def dispatch_message(cls, stream, message):
|
||||||
"""
|
"""
|
||||||
Sends a message to Websocket client
|
Sends a message to Websocket client
|
||||||
|
|
||||||
@ -71,7 +71,13 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
|
|
||||||
# ZMQ responses are encoded in JSON
|
# ZMQ responses are encoded in JSON
|
||||||
# format is a JSON array: [session ID, JSON-RPC response]
|
# format is a JSON array: [session ID, JSON-RPC response]
|
||||||
json_message = json_decode(message[1])
|
try:
|
||||||
|
json_message = json_decode(message[1])
|
||||||
|
except ValueError as e:
|
||||||
|
stream.send_string("Cannot decode message!")
|
||||||
|
log.critical("Couldn't decode message: {}".format(e))
|
||||||
|
return
|
||||||
|
|
||||||
session_id = json_message[0]
|
session_id = json_message[0]
|
||||||
jsonrpc_response = json_message[1]
|
jsonrpc_response = json_message[1]
|
||||||
|
|
||||||
@ -94,8 +100,8 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
# Make sure the destination is not already registered
|
# Make sure the destination is not already registered
|
||||||
# by another module for instance
|
# by another module for instance
|
||||||
assert destination not in cls.destinations
|
assert destination not in cls.destinations
|
||||||
log.info("registering {} as a destination for {}".format(destination,
|
log.debug("registering {} as a destination for the {} module".format(destination,
|
||||||
module))
|
module))
|
||||||
cls.destinations[destination] = module
|
cls.destinations[destination] = module
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
@ -119,8 +125,8 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
request = json_decode(message)
|
request = json_decode(message)
|
||||||
jsonrpc_version = request["jsonrpc"]
|
jsonrpc_version = request["jsonrpc"]
|
||||||
method = request["method"]
|
method = request["method"]
|
||||||
# warning: notifications cannot be sent by a client because check for an "id" here
|
# This is a JSON-RPC notification if request_id is None
|
||||||
request_id = request["id"]
|
request_id = request.get("id")
|
||||||
except:
|
except:
|
||||||
return self.write_message(JSONRPCParseError()())
|
return self.write_message(JSONRPCParseError()())
|
||||||
|
|
||||||
@ -128,7 +134,11 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
return self.write_message(JSONRPCInvalidRequest()())
|
return self.write_message(JSONRPCInvalidRequest()())
|
||||||
|
|
||||||
if method not in self.destinations:
|
if method not in self.destinations:
|
||||||
return self.write_message(JSONRPCMethodNotFound(request_id)())
|
if request_id:
|
||||||
|
return self.write_message(JSONRPCMethodNotFound(request_id)())
|
||||||
|
else:
|
||||||
|
# This is a notification, silently ignore this error...
|
||||||
|
return
|
||||||
|
|
||||||
module = self.destinations[method]
|
module = self.destinations[method]
|
||||||
# ZMQ requests are encoded in JSON
|
# ZMQ requests are encoded in JSON
|
||||||
@ -136,7 +146,7 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
zmq_request = [self.session_id, request]
|
zmq_request = [self.session_id, request]
|
||||||
# Route to the correct module
|
# Route to the correct module
|
||||||
self.zmq_router.send_string(module, zmq.SNDMORE)
|
self.zmq_router.send_string(module, zmq.SNDMORE)
|
||||||
# Send the encoded JSON request
|
# Send the JSON request
|
||||||
self.zmq_router.send_json(zmq_request)
|
self.zmq_router.send_json(zmq_request)
|
||||||
|
|
||||||
def on_close(self):
|
def on_close(self):
|
||||||
@ -146,3 +156,14 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
|
|
||||||
log.info("Websocket client {} disconnected".format(self.session_id))
|
log.info("Websocket client {} disconnected".format(self.session_id))
|
||||||
self.clients.remove(self)
|
self.clients.remove(self)
|
||||||
|
|
||||||
|
# Reset the modules if there are no clients anymore
|
||||||
|
# Modules must implement a reset destination
|
||||||
|
if not self.clients:
|
||||||
|
for destination, module in self.destinations.items():
|
||||||
|
if destination.endswith("reset"):
|
||||||
|
# Route to the correct module
|
||||||
|
self.zmq_router.send_string(module, zmq.SNDMORE)
|
||||||
|
# Send the JSON request
|
||||||
|
notification = JSONRPCNotification(destination)()
|
||||||
|
self.zmq_router.send_json([self.session_id, notification])
|
||||||
|
@ -159,8 +159,10 @@ class JSONRPCRequest(JSONRPCObject):
|
|||||||
:param request_id: JSON-RPC identifier (generated by default)
|
:param request_id: JSON-RPC identifier (generated by default)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, method, params=None, request_id=str(uuid.uuid1())):
|
def __init__(self, method, params=None, request_id=None):
|
||||||
JSONRPCObject.__init__(self)
|
JSONRPCObject.__init__(self)
|
||||||
|
if request_id == None:
|
||||||
|
request_id = str(uuid.uuid4())
|
||||||
self.id = request_id
|
self.id = request_id
|
||||||
self.method = method
|
self.method = method
|
||||||
if params:
|
if params:
|
||||||
|
@ -24,7 +24,7 @@ import gns3server
|
|||||||
|
|
||||||
# command line options
|
# command line options
|
||||||
from tornado.options import define
|
from tornado.options import define
|
||||||
define("host", default="127.0.0.1", help="run on the given host/IP address", type=str)
|
define("host", default="0.0.0.0", help="run on the given host/IP address", type=str)
|
||||||
define("port", default=8000, help="run on the given port", type=int)
|
define("port", default=8000, help="run on the given port", type=int)
|
||||||
define("ipc", default=False, help="use IPC for module communication", type=bool)
|
define("ipc", default=False, help="use IPC for module communication", type=bool)
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class ModuleManager(object):
|
|||||||
if issubclass(module_class[1], IModule):
|
if issubclass(module_class[1], IModule):
|
||||||
# make sure the module class has IModule as a parent
|
# make sure the module class has IModule as a parent
|
||||||
if module_class[1].__module__ == name:
|
if module_class[1].__module__ == name:
|
||||||
log.info("found and loading {} module".format(module_class[0].lower()))
|
log.info("loading {} module".format(module_class[0].lower()))
|
||||||
info = Module(name=module_class[0].lower(), cls=module_class[1])
|
info = Module(name=module_class[0].lower(), cls=module_class[1])
|
||||||
self._modules.append(info)
|
self._modules.append(info)
|
||||||
except:
|
except:
|
||||||
|
@ -92,6 +92,10 @@ class IModule(multiprocessing.Process):
|
|||||||
stream.on_recv(callback)
|
stream.on_recv(callback)
|
||||||
return stream
|
return stream
|
||||||
|
|
||||||
|
# def add_periodic_callback(self, callback, time):
|
||||||
|
#
|
||||||
|
# self.test = zmq.eventloop.ioloop.PeriodicCallback(callback, time, self._ioloop).start()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
Starts the event loop
|
Starts the event loop
|
||||||
@ -158,9 +162,9 @@ class IModule(multiprocessing.Process):
|
|||||||
|
|
||||||
# add session to the response
|
# add session to the response
|
||||||
response = [self._current_session, jsonrpc_response]
|
response = [self._current_session, jsonrpc_response]
|
||||||
log.info("ZeroMQ client ({}) sending JSON-RPC custom error {} for call id {}".format(self.name,
|
log.info("ZeroMQ client ({}) sending JSON-RPC custom error: {} for call id {}".format(self.name,
|
||||||
message,
|
message,
|
||||||
self._current_call_id))
|
self._current_call_id))
|
||||||
self._stream.send_json(response)
|
self._stream.send_json(response)
|
||||||
|
|
||||||
def _decode_request(self, request):
|
def _decode_request(self, request):
|
||||||
@ -188,7 +192,12 @@ class IModule(multiprocessing.Process):
|
|||||||
return
|
return
|
||||||
|
|
||||||
log.debug("Routing request to {}: {}".format(destination, request[1]))
|
log.debug("Routing request to {}: {}".format(destination, request[1]))
|
||||||
self.destination[destination](self, params)
|
|
||||||
|
try:
|
||||||
|
self.destination[destination](self, params)
|
||||||
|
except Exception as e:
|
||||||
|
log.error("uncaught exception {type}".format(type=type(e)), exc_info=1)
|
||||||
|
self.send_custom_error("uncaught exception {type}: {string}".format(type=type(e), string=str(e)))
|
||||||
|
|
||||||
def destinations(self):
|
def destinations(self):
|
||||||
"""
|
"""
|
||||||
|
@ -15,13 +15,18 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dynamips server module.
|
||||||
|
"""
|
||||||
|
|
||||||
from gns3server.modules import IModule
|
from gns3server.modules import IModule
|
||||||
import gns3server.jsonrpc as jsonrpc
|
import gns3server.jsonrpc as jsonrpc
|
||||||
|
|
||||||
from .hypervisor import Hypervisor
|
from .hypervisor import Hypervisor
|
||||||
from .hypervisor_manager import HypervisorManager
|
from .hypervisor_manager import HypervisorManager
|
||||||
from .dynamips_error import DynamipsError
|
from .dynamips_error import DynamipsError
|
||||||
|
|
||||||
# nodes
|
# Nodes
|
||||||
from .nodes.router import Router
|
from .nodes.router import Router
|
||||||
from .nodes.c1700 import C1700
|
from .nodes.c1700 import C1700
|
||||||
from .nodes.c2600 import C2600
|
from .nodes.c2600 import C2600
|
||||||
@ -37,7 +42,7 @@ from .nodes.atm_bridge import ATMBridge
|
|||||||
from .nodes.frame_relay_switch import FrameRelaySwitch
|
from .nodes.frame_relay_switch import FrameRelaySwitch
|
||||||
from .nodes.hub import Hub
|
from .nodes.hub import Hub
|
||||||
|
|
||||||
# adapters
|
# Adapters
|
||||||
from .adapters.c7200_io_2fe import C7200_IO_2FE
|
from .adapters.c7200_io_2fe import C7200_IO_2FE
|
||||||
from .adapters.c7200_io_fe import C7200_IO_FE
|
from .adapters.c7200_io_fe import C7200_IO_FE
|
||||||
from .adapters.c7200_io_ge_e import C7200_IO_GE_E
|
from .adapters.c7200_io_ge_e import C7200_IO_GE_E
|
||||||
@ -71,35 +76,188 @@ from .nios.nio_fifo import NIO_FIFO
|
|||||||
from .nios.nio_mcast import NIO_Mcast
|
from .nios.nio_mcast import NIO_Mcast
|
||||||
from .nios.nio_null import NIO_Null
|
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 logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Dynamips(IModule):
|
class Dynamips(IModule):
|
||||||
|
"""
|
||||||
|
Dynamips module.
|
||||||
|
|
||||||
|
:param name: module name
|
||||||
|
:param args: arguments for the module
|
||||||
|
:param kwargs: named arguments for the module
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, name=None, args=(), kwargs={}):
|
def __init__(self, name=None, args=(), kwargs={}):
|
||||||
IModule.__init__(self, name=name, args=args, kwargs=kwargs)
|
IModule.__init__(self, name=name, args=args, kwargs=kwargs)
|
||||||
|
|
||||||
# start the hypervisor manager
|
self._hypervisor_manager = None
|
||||||
#self._hypervisor_manager = HypervisorManager("/usr/bin/dynamips", "/tmp")
|
self._routers = {}
|
||||||
|
self._ethernet_switches = {}
|
||||||
|
self._frame_relay_switches = {}
|
||||||
|
self._atm_switches = {}
|
||||||
|
self._ethernet_hubs = {}
|
||||||
|
|
||||||
|
# def __del__(self):
|
||||||
|
#
|
||||||
|
# self._hypervisor_manager.stop_all_hypervisors()
|
||||||
|
|
||||||
|
@IModule.route("dynamips.reset")
|
||||||
|
def reset(self, request):
|
||||||
|
"""
|
||||||
|
Resets the module.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
# stop all Dynamips hypervisors
|
||||||
|
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()
|
||||||
|
|
||||||
|
log.info("dynamips module has been reset")
|
||||||
|
|
||||||
|
@IModule.route("dynamips.settings")
|
||||||
|
def settings(self, request):
|
||||||
|
"""
|
||||||
|
Set or update settings.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("Create")
|
||||||
|
if not self._hypervisor_manager:
|
||||||
|
self._hypervisor_manager = HypervisorManager(request["path"], "/tmp")
|
||||||
|
|
||||||
|
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")
|
@IModule.route("dynamips.echo")
|
||||||
def echo(self, request):
|
def echo(self, request):
|
||||||
|
"""
|
||||||
|
Echo end point for testing purposes.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
if request == None:
|
if request == None:
|
||||||
self.send_param_error()
|
self.send_param_error()
|
||||||
return
|
else:
|
||||||
log.debug("received request {}".format(request))
|
log.debug("received request {}".format(request))
|
||||||
self.send_response(request)
|
self.send_response(request)
|
||||||
|
|
||||||
@IModule.route("dynamips.create_vm")
|
def create_nio(self, node, request):
|
||||||
def create_vm(self, request):
|
|
||||||
print("Create VM!")
|
|
||||||
log.debug("received request {}".format(request))
|
|
||||||
self.send_response(request)
|
|
||||||
|
|
||||||
@IModule.route("dynamips.start_vm")
|
nio = None
|
||||||
def start_vm(self, request):
|
if request["nio"] == "NIO_UDP":
|
||||||
print("Start VM!")
|
lport = request["lport"]
|
||||||
log.debug("received request {}".format(request))
|
rhost = request["rhost"]
|
||||||
self.send_response(request)
|
rport = request["rport"]
|
||||||
|
nio = NIO_UDP(node.hypervisor, lport, rhost, rport)
|
||||||
|
elif request["nio"] == "NIO_GenericEthernet":
|
||||||
|
ethernet_device = request["ethernet_device"]
|
||||||
|
nio = NIO_GenericEthernet(node.hypervisor, ethernet_device)
|
||||||
|
elif request["nio"] == "NIO_LinuxEthernet":
|
||||||
|
ethernet_device = request["ethernet_device"]
|
||||||
|
nio = NIO_LinuxEthernet(node.hypervisor, ethernet_device)
|
||||||
|
elif request["nio"] == "NIO_TAP":
|
||||||
|
tap_device = request["tap_device"]
|
||||||
|
nio = NIO_TAP(node.hypervisor, tap_device)
|
||||||
|
elif request["nio"] == "NIO_UNIX":
|
||||||
|
local_file = request["local_file"]
|
||||||
|
remote_file = request["remote_file"]
|
||||||
|
nio = NIO_UNIX(node.hypervisor, local_file, remote_file)
|
||||||
|
elif request["nio"] == "NIO_VDE":
|
||||||
|
control_file = request["control_file"]
|
||||||
|
local_file = request["local_file"]
|
||||||
|
nio = NIO_VDE(node.hypervisor, control_file, local_file)
|
||||||
|
elif request["nio"] == "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
|
||||||
|
"""
|
||||||
|
|
||||||
|
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,
|
||||||
|
"lhost": host}
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def set_ghost_ios(self, router):
|
||||||
|
|
||||||
|
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
|
||||||
|
ghost.start()
|
||||||
|
ghost.stop()
|
||||||
|
ghost.delete()
|
||||||
|
|
||||||
|
router.ghost_status = 2
|
||||||
|
router.ghost_file = ghost_instance
|
||||||
|
|
||||||
|
@IModule.route("dynamips.nio.get_interfaces")
|
||||||
|
def nio_get_interfaces(self, request):
|
||||||
|
"""
|
||||||
|
Get all the network interfaces on this host.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
import netifaces
|
||||||
|
self.send_response(netifaces.interfaces())
|
||||||
|
@ -124,6 +124,17 @@ class Adapter(object):
|
|||||||
|
|
||||||
self._ports[port_id] = None
|
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 object
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._ports[port_id]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ports(self):
|
def ports(self):
|
||||||
"""
|
"""
|
||||||
|
@ -33,11 +33,3 @@ class C1700_MB_1FE(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,16 +29,8 @@ class C1700_MB_WIC1(Adapter):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "C1700_MB_WIC1"
|
return "C1700-MB-WIC1"
|
||||||
|
|
||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "N/A"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "N/A"
|
|
||||||
|
@ -33,11 +33,3 @@ class C2600_MB_1E(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -34,11 +34,3 @@ class C2600_MB_1FE(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -33,11 +33,3 @@ class C2600_MB_2E(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -33,11 +33,3 @@ class C2600_MB_2FE(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -28,16 +28,8 @@ class C7200_IO_2FE(Adapter):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "C7200_IO_2FE"
|
return "C7200-IO-2FE"
|
||||||
|
|
||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -28,16 +28,8 @@ class C7200_IO_FE(Adapter):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "C7200_IO_FE"
|
return "C7200-IO-FE"
|
||||||
|
|
||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -33,11 +33,3 @@ class C7200_IO_GE_E(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "GigabitEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -30,11 +30,3 @@ class GT96100_FE(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -34,11 +34,3 @@ class Leopard_2FE(Adapter):
|
|||||||
def removable(self):
|
def removable(self):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class NM_16ESW(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "NM-16ESW"
|
return "NM-16ESW"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class NM_1E(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "NM-1E"
|
return "NM-1E"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class NM_1FE_TX(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "NM-1FE-TX"
|
return "NM-1FE-TX"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class NM_4E(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "NM-4E"
|
return "NM-4E"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class NM_4T(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "NM-4T"
|
return "NM-4T"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_2FE_TX(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-2FE-TX"
|
return "PA-2FE-TX"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_4E(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-4E"
|
return "PA-4E"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_4T(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-4T+"
|
return "PA-4T+"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_8E(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-8E"
|
return "PA-8E"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_8T(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-8T"
|
return "PA-8T"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_A1(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-A1"
|
return "PA-A1"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "ATM"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_FE_TX(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-FE-TX"
|
return "PA-FE-TX"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "FastEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_GE(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-GE"
|
return "PA-GE"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "GigabitEthernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
@ -29,11 +29,3 @@ class PA_POS_OC3(Adapter):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
return "PA-POS-OC3"
|
return "PA-POS-OC3"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "POS"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "SONET"
|
|
||||||
|
@ -29,14 +29,6 @@ class WIC_1ENET(object):
|
|||||||
|
|
||||||
return "WIC-1ENET"
|
return "WIC-1ENET"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Ethernet"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
"""
|
"""
|
||||||
|
@ -29,14 +29,6 @@ class WIC_1T(object):
|
|||||||
|
|
||||||
return "WIC-1T"
|
return "WIC-1T"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
"""
|
"""
|
||||||
|
@ -29,14 +29,6 @@ class WIC_2T(object):
|
|||||||
|
|
||||||
return "WIC-2T"
|
return "WIC-2T"
|
||||||
|
|
||||||
def interface_type(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
def medium(self):
|
|
||||||
|
|
||||||
return "Serial"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
"""
|
"""
|
||||||
|
0
gns3server/modules/dynamips/backends/__init__.py
Normal file
0
gns3server/modules/dynamips/backends/__init__.py
Normal file
201
gns3server/modules/dynamips/backends/atmsw.py
Normal file
201
gns3server/modules/dynamips/backends/atmsw.py
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
import re
|
||||||
|
from gns3server.modules import IModule
|
||||||
|
from ..nodes.atm_switch import ATMSwitch
|
||||||
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ATMSW(object):
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.create")
|
||||||
|
def atmsw_create(self, request):
|
||||||
|
"""
|
||||||
|
Creates a new ATM switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = None
|
||||||
|
if request and "name" in request:
|
||||||
|
name = request["name"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_switch()
|
||||||
|
atmsw = ATMSwitch(hypervisor, name)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"name": atmsw.name,
|
||||||
|
"id": atmsw.id}
|
||||||
|
|
||||||
|
self._atm_switches[atmsw.id] = atmsw
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.delete")
|
||||||
|
def atmsw_delete(self, request):
|
||||||
|
"""
|
||||||
|
Deletes a ATM switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
atmsw_id = request["id"]
|
||||||
|
atmsw = self._atm_switches[atmsw_id]
|
||||||
|
try:
|
||||||
|
atmsw.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.update")
|
||||||
|
def atmsw_update(self, request):
|
||||||
|
"""
|
||||||
|
Updates a ATM switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
atmsw_id = request["id"]
|
||||||
|
atmsw = self._atm_switches[atmsw_id]
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.allocate_udp_port")
|
||||||
|
def atmsw_allocate_udp_port(self, request):
|
||||||
|
"""
|
||||||
|
Allocates a UDP port in order to create an UDP NIO for an
|
||||||
|
ATM switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
atmsw_id = request["id"]
|
||||||
|
atmsw = self._atm_switches[atmsw_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# allocate a new UDP port
|
||||||
|
response = self.allocate_udp_port(atmsw)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.add_nio")
|
||||||
|
def atmsw_add_nio(self, request):
|
||||||
|
"""
|
||||||
|
Adds an NIO (Network Input/Output) for an ATM switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
atmsw_id = request["id"]
|
||||||
|
atmsw = self._atm_switches[atmsw_id]
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
mapping = request["mapping"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = self.create_nio(atmsw, request)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
atmsw.add_nio(nio, port)
|
||||||
|
pvc_entry = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
|
||||||
|
for source, destination in mapping.items():
|
||||||
|
match_source_pvc = pvc_entry.search(source)
|
||||||
|
match_destination_pvc = pvc_entry.search(destination)
|
||||||
|
if match_source_pvc and match_destination_pvc:
|
||||||
|
# add the virtual channels mapped with this port/nio
|
||||||
|
source_port, source_vpi, source_vci = map(int, match_source_pvc.group(1, 2, 3))
|
||||||
|
destination_port, destination_vpi, destination_vci = map(int, match_destination_pvc.group(1, 2, 3))
|
||||||
|
if atmsw.has_port(destination_port):
|
||||||
|
if (source_port, source_vpi, source_vci) not in atmsw.mapping and \
|
||||||
|
(destination_port, destination_vpi, destination_vci) not in atmsw.mapping:
|
||||||
|
atmsw.map_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
|
||||||
|
atmsw.map_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci)
|
||||||
|
else:
|
||||||
|
# add the virtual paths mapped with this port/nio
|
||||||
|
source_port, source_vpi = map(int, source.split(':'))
|
||||||
|
destination_port, destination_vpi = map(int, destination.split(':'))
|
||||||
|
if atmsw.has_port(destination_port):
|
||||||
|
if (source_port, source_vpi) not in atmsw.mapping and (destination_port, destination_vpi) not in atmsw.mapping:
|
||||||
|
atmsw.map_vp(source_port, source_vpi, destination_port, destination_vpi)
|
||||||
|
atmsw.map_vp(destination_port, destination_vpi, source_port, source_vpi)
|
||||||
|
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.atmsw.delete_nio")
|
||||||
|
def atmsw_delete_nio(self, request):
|
||||||
|
"""
|
||||||
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
atmsw_id = request["id"]
|
||||||
|
atmsw = self._atm_switches[atmsw_id]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
for source, destination in atmsw.mapping.copy().items():
|
||||||
|
if len(source) == 3 and len(destination) == 3:
|
||||||
|
# remove the virtual channels mapped with this port/nio
|
||||||
|
source_port, source_vpi, source_vci = source
|
||||||
|
destination_port, destination_vpi, destination_vci = destination
|
||||||
|
if port == source_port:
|
||||||
|
atmsw.unmap_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
|
||||||
|
atmsw.unmap_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci)
|
||||||
|
else:
|
||||||
|
# remove the virtual paths mapped with this port/nio
|
||||||
|
source_port, source_vpi = source
|
||||||
|
destination_port, destination_vpi = destination
|
||||||
|
if port == source_port:
|
||||||
|
atmsw.unmap_vp(source_port, source_vpi, destination_port, destination_vpi)
|
||||||
|
atmsw.unmap_vp(destination_port, destination_vpi, source_port, source_vpi)
|
||||||
|
|
||||||
|
nio = atmsw.remove_nio(port)
|
||||||
|
nio.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
162
gns3server/modules/dynamips/backends/ethhub.py
Normal file
162
gns3server/modules/dynamips/backends/ethhub.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.modules import IModule
|
||||||
|
from ..nodes.hub import Hub
|
||||||
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ETHHUB(object):
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.create")
|
||||||
|
def ethhub_create(self, request):
|
||||||
|
"""
|
||||||
|
Creates a new Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = None
|
||||||
|
if request and "name" in request:
|
||||||
|
name = request["name"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_switch()
|
||||||
|
ethhub = Hub(hypervisor, name)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"name": ethhub.name,
|
||||||
|
"id": ethhub.id}
|
||||||
|
|
||||||
|
self._ethernet_hubs[ethhub.id] = ethhub
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.delete")
|
||||||
|
def ethhub_delete(self, request):
|
||||||
|
"""
|
||||||
|
Deletes a Ethernet hub.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethhub_id = request["id"]
|
||||||
|
ethhub = self._ethernet_hubs[ethhub_id]
|
||||||
|
try:
|
||||||
|
ethhub.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.update")
|
||||||
|
def ethhub_update(self, request):
|
||||||
|
"""
|
||||||
|
Updates a Ethernet hub.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethhub_id = request["id"]
|
||||||
|
ethhub = self._ethernet_hubs[ethhub_id]
|
||||||
|
#ports = request["ports"]
|
||||||
|
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.allocate_udp_port")
|
||||||
|
def ethhub_allocate_udp_port(self, request):
|
||||||
|
"""
|
||||||
|
Allocates a UDP port in order to create an UDP NIO for an
|
||||||
|
Ethernet hub.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethhub_id = request["id"]
|
||||||
|
ethhub = self._ethernet_hubs[ethhub_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# allocate a new UDP port
|
||||||
|
response = self.allocate_udp_port(ethhub)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.add_nio")
|
||||||
|
def ethhub_add_nio(self, request):
|
||||||
|
"""
|
||||||
|
Adds an NIO (Network Input/Output) for an Ethernet hub.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethhub_id = request["id"]
|
||||||
|
ethhub = self._ethernet_hubs[ethhub_id]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = self.create_nio(ethhub, request)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
ethhub.add_nio(nio, port)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethhub.delete_nio")
|
||||||
|
def ethsw_delete_nio(self, request):
|
||||||
|
"""
|
||||||
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethhub_id = request["id"]
|
||||||
|
ethhub = self._ethernet_hubs[ethhub_id]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = ethhub.remove_nio(port)
|
||||||
|
nio.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
180
gns3server/modules/dynamips/backends/ethsw.py
Normal file
180
gns3server/modules/dynamips/backends/ethsw.py
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.modules import IModule
|
||||||
|
from ..nodes.ethernet_switch import EthernetSwitch
|
||||||
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ETHSW(object):
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.create")
|
||||||
|
def ethsw_create(self, request):
|
||||||
|
"""
|
||||||
|
Creates a new Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = None
|
||||||
|
if request and "name" in request:
|
||||||
|
name = request["name"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_switch()
|
||||||
|
ethsw = EthernetSwitch(hypervisor, name)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"name": ethsw.name,
|
||||||
|
"id": ethsw.id}
|
||||||
|
|
||||||
|
self._ethernet_switches[ethsw.id] = ethsw
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.delete")
|
||||||
|
def ethsw_delete(self, request):
|
||||||
|
"""
|
||||||
|
Deletes a Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethsw_id = request["id"]
|
||||||
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
|
try:
|
||||||
|
ethsw.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.update")
|
||||||
|
def ethsw_update(self, request):
|
||||||
|
"""
|
||||||
|
Updates a Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethsw_id = request["id"]
|
||||||
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
|
ports = request["ports"]
|
||||||
|
|
||||||
|
for port, info in ports.items():
|
||||||
|
vlan = info["vlan"]
|
||||||
|
port_type = info["type"]
|
||||||
|
if port_type == "access":
|
||||||
|
ethsw.set_access_port(int(port), vlan)
|
||||||
|
elif port_type == "dot1q":
|
||||||
|
ethsw.set_dot1q_port(int(port), vlan)
|
||||||
|
elif port_type == "qinq":
|
||||||
|
ethsw.set_qinq_port(int(port), vlan)
|
||||||
|
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.allocate_udp_port")
|
||||||
|
def ethsw_allocate_udp_port(self, request):
|
||||||
|
"""
|
||||||
|
Allocates a UDP port in order to create an UDP NIO for an
|
||||||
|
Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethsw_id = request["id"]
|
||||||
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# allocate a new UDP port
|
||||||
|
response = self.allocate_udp_port(ethsw)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.add_nio")
|
||||||
|
def ethsw_add_nio(self, request):
|
||||||
|
"""
|
||||||
|
Adds an NIO (Network Input/Output) for an Ethernet switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethsw_id = request["id"]
|
||||||
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
vlan = request["vlan"]
|
||||||
|
port_type = request["port_type"]
|
||||||
|
try:
|
||||||
|
nio = self.create_nio(ethsw, request)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
ethsw.add_nio(nio, port)
|
||||||
|
if port_type == "access":
|
||||||
|
ethsw.set_access_port(port, vlan)
|
||||||
|
elif port_type == "dot1q":
|
||||||
|
ethsw.set_dot1q_port(port, vlan)
|
||||||
|
elif port_type == "qinq":
|
||||||
|
ethsw.set_qinq_port(port, vlan)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.ethsw.delete_nio")
|
||||||
|
def ethsw_delete_nio(self, request):
|
||||||
|
"""
|
||||||
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
ethsw_id = request["id"]
|
||||||
|
ethsw = self._ethernet_switches[ethsw_id]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = ethsw.remove_nio(port)
|
||||||
|
nio.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
179
gns3server/modules/dynamips/backends/frsw.py
Normal file
179
gns3server/modules/dynamips/backends/frsw.py
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.modules import IModule
|
||||||
|
from ..nodes.frame_relay_switch import FrameRelaySwitch
|
||||||
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class FRSW(object):
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.create")
|
||||||
|
def frsw_create(self, request):
|
||||||
|
"""
|
||||||
|
Creates a new Frame-Relay switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = None
|
||||||
|
if request and "name" in request:
|
||||||
|
name = request["name"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_switch()
|
||||||
|
frsw = FrameRelaySwitch(hypervisor, name)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"name": frsw.name,
|
||||||
|
"id": frsw.id}
|
||||||
|
|
||||||
|
self._frame_relay_switches[frsw.id] = frsw
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.delete")
|
||||||
|
def frsw_delete(self, request):
|
||||||
|
"""
|
||||||
|
Deletes a Frame Relay switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
frsw_id = request["id"]
|
||||||
|
frsw = self._frame_relay_switches[frsw_id]
|
||||||
|
try:
|
||||||
|
frsw.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.update")
|
||||||
|
def frsw_update(self, request):
|
||||||
|
"""
|
||||||
|
Updates a Frame Relay switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
frsw_id = request["id"]
|
||||||
|
frsw = self._frame_relay_switches[frsw_id]
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.allocate_udp_port")
|
||||||
|
def frsw_allocate_udp_port(self, request):
|
||||||
|
"""
|
||||||
|
Allocates a UDP port in order to create an UDP NIO for an
|
||||||
|
Frame Relay switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
frsw_id = request["id"]
|
||||||
|
frsw = self._frame_relay_switches[frsw_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# allocate a new UDP port
|
||||||
|
response = self.allocate_udp_port(frsw)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.add_nio")
|
||||||
|
def frsw_add_nio(self, request):
|
||||||
|
"""
|
||||||
|
Adds an NIO (Network Input/Output) for an Frame-Relay switch.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
frsw_id = request["id"]
|
||||||
|
frsw = self._frame_relay_switches[frsw_id]
|
||||||
|
|
||||||
|
port = request["port"]
|
||||||
|
mapping = request["mapping"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = self.create_nio(frsw, request)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
frsw.add_nio(nio, port)
|
||||||
|
|
||||||
|
# add the VCs mapped with this port/nio
|
||||||
|
for source, destination in mapping.items():
|
||||||
|
source_port, source_dlci = map(int, source.split(':'))
|
||||||
|
destination_port, destination_dlci = map(int, destination.split(':'))
|
||||||
|
if frsw.has_port(destination_port):
|
||||||
|
if (source_port, source_dlci) not in frsw.mapping and (destination_port, destination_dlci) not in frsw.mapping:
|
||||||
|
frsw.map_vc(source_port, source_dlci, destination_port, destination_dlci)
|
||||||
|
frsw.map_vc(destination_port, destination_dlci, source_port, source_dlci)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.frsw.delete_nio")
|
||||||
|
def frsw_delete_nio(self, request):
|
||||||
|
"""
|
||||||
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
frsw_id = request["id"]
|
||||||
|
frsw = self._frame_relay_switches[frsw_id]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# remove the VCs mapped with this port/nio
|
||||||
|
for source, destination in frsw.mapping.copy().items():
|
||||||
|
source_port, source_dlci = source
|
||||||
|
destination_port, destination_dlci = destination
|
||||||
|
if port == source_port:
|
||||||
|
frsw.unmap_vc(source_port, source_dlci, destination_port, destination_dlci)
|
||||||
|
frsw.unmap_vc(destination_port, destination_dlci, source_port, source_dlci)
|
||||||
|
|
||||||
|
nio = frsw.remove_nio(port)
|
||||||
|
nio.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
367
gns3server/modules/dynamips/backends/vm.py
Normal file
367
gns3server/modules/dynamips/backends/vm.py
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from gns3server.modules import IModule
|
||||||
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
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 ..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_1enet import WIC_1ENET
|
||||||
|
from ..adapters.wic_1t import WIC_1T
|
||||||
|
from ..adapters.wic_2t import WIC_2T
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
ADAPTER_MATRIX = {"C7200_IO_2FE": C7200_IO_2FE,
|
||||||
|
"C7200_IO_FE": C7200_IO_FE,
|
||||||
|
"C7200-IO-GE-E": C7200_IO_GE_E,
|
||||||
|
"NM-16ESW": NM_16ESW,
|
||||||
|
"NM-1E": NM_1E,
|
||||||
|
"NM-1FE-TX": NM_1FE_TX,
|
||||||
|
"NM-4E": NM_4E,
|
||||||
|
"NM-4T": NM_4T,
|
||||||
|
"PA-2FE-TX": PA_2FE_TX,
|
||||||
|
"PA-4E": PA_4E,
|
||||||
|
"PA-4T+": PA_4T,
|
||||||
|
"PA-8E": PA_8E,
|
||||||
|
"PA-8T": PA_8T,
|
||||||
|
"PA-A1": PA_A1,
|
||||||
|
"PA-FE-TX": PA_FE_TX,
|
||||||
|
"PA-GE": PA_GE,
|
||||||
|
"PA-POS-OC3": PA_POS_OC3}
|
||||||
|
|
||||||
|
WIC_MATRIX = {"WIC-1ENET": WIC_1ENET,
|
||||||
|
"WIC-1T": WIC_1T,
|
||||||
|
"WIC-2T": WIC_2T}
|
||||||
|
|
||||||
|
PLATFORMS = {'c1700': C1700,
|
||||||
|
'c2600': C2600,
|
||||||
|
'c2691': C2691,
|
||||||
|
'c3725': C3725,
|
||||||
|
'c3745': C3745,
|
||||||
|
'c3600': C3600,
|
||||||
|
'c7200': C7200}
|
||||||
|
|
||||||
|
|
||||||
|
class VM(object):
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.create")
|
||||||
|
def vm_create(self, request):
|
||||||
|
"""
|
||||||
|
Creates a new VM (router).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
if request == None:
|
||||||
|
self.send_param_error()
|
||||||
|
else:
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
|
||||||
|
#TODO: JSON schema validation
|
||||||
|
#name = request["name"]
|
||||||
|
platform = request["platform"]
|
||||||
|
image = request["image"]
|
||||||
|
ram = request["ram"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_router(image, ram)
|
||||||
|
router = PLATFORMS[platform](hypervisor)
|
||||||
|
router.ram = ram
|
||||||
|
router.image = image
|
||||||
|
router.sparsemem = self._hypervisor_manager.sparse_memory_support
|
||||||
|
router.mmap = self._hypervisor_manager.mmap_support
|
||||||
|
|
||||||
|
# JIT sharing support
|
||||||
|
if self._hypervisor_manager.jit_sharing_support:
|
||||||
|
jitsharing_groups = hypervisor.jitsharing_groups
|
||||||
|
ios_image = os.path.basename(image)
|
||||||
|
if ios_image in jitsharing_groups:
|
||||||
|
router.jit_sharing_group = jitsharing_groups[ios_image]
|
||||||
|
else:
|
||||||
|
new_jit_group = -1
|
||||||
|
for jit_group in range(0, 127):
|
||||||
|
if jit_group not in jitsharing_groups.values():
|
||||||
|
new_jit_group = jit_group
|
||||||
|
break
|
||||||
|
if new_jit_group == -1:
|
||||||
|
raise DynamipsError("All JIT groups are allocated!")
|
||||||
|
router.jit_sharing_group = new_jit_group
|
||||||
|
|
||||||
|
# Ghost IOS support
|
||||||
|
if self._hypervisor_manager.ghost_ios_support:
|
||||||
|
self.set_ghost_ios(router)
|
||||||
|
|
||||||
|
except DynamipsError as e:
|
||||||
|
hypervisor.decrease_memory_load(ram)
|
||||||
|
if hypervisor.memory_load == 0 and not hypervisor.devices:
|
||||||
|
hypervisor.stop()
|
||||||
|
self._hypervisor_manager.hypervisors.remove(hypervisor)
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
response = {"name": router.name,
|
||||||
|
"id": router.id}
|
||||||
|
defaults = router.defaults()
|
||||||
|
response.update(defaults)
|
||||||
|
self._routers[router.id] = router
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.delete")
|
||||||
|
def vm_delete(self, request):
|
||||||
|
"""
|
||||||
|
Deletes a VM (router).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
try:
|
||||||
|
router.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.start")
|
||||||
|
def vm_start(self, request):
|
||||||
|
"""
|
||||||
|
Starts a VM (router)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
try:
|
||||||
|
router.start()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.stop")
|
||||||
|
def vm_stop(self, request):
|
||||||
|
"""
|
||||||
|
Stops a VM (router)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
try:
|
||||||
|
router.stop()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.suspend")
|
||||||
|
def vm_suspend(self, request):
|
||||||
|
"""
|
||||||
|
Suspends a VM (router)
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
try:
|
||||||
|
router.suspend()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.update")
|
||||||
|
def vm_update(self, request):
|
||||||
|
"""
|
||||||
|
Updates settings for a VM (router).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
|
||||||
|
# update the settings
|
||||||
|
for name, value in request.items():
|
||||||
|
if hasattr(router, name) and getattr(router, name) != value:
|
||||||
|
try:
|
||||||
|
setattr(router, name, value)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
elif name.startswith("slot") and value in ADAPTER_MATRIX:
|
||||||
|
slot_id = int(name[-1])
|
||||||
|
adapter_name = value
|
||||||
|
adapter = ADAPTER_MATRIX[adapter_name]()
|
||||||
|
try:
|
||||||
|
if router.slots[slot_id] and type(router.slots[slot_id]) != type(adapter):
|
||||||
|
router.slot_remove_binding(slot_id)
|
||||||
|
router.slot_add_binding(slot_id, adapter)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
elif name.startswith("slot") and value == None:
|
||||||
|
slot_id = int(name[-1])
|
||||||
|
if router.slots[slot_id]:
|
||||||
|
try:
|
||||||
|
router.slot_remove_binding(slot_id)
|
||||||
|
except:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
elif name.startswith("wic") and value in WIC_MATRIX:
|
||||||
|
wic_slot_id = int(name[-1])
|
||||||
|
wic_name = value
|
||||||
|
wic = WIC_MATRIX[wic_name]()
|
||||||
|
try:
|
||||||
|
if router.slots[0].wics[wic_slot_id] and type(router.slots[0].wics[wic_slot_id]) != type(wic):
|
||||||
|
router.uninstall_wic(wic_slot_id)
|
||||||
|
router.install_wic(wic_slot_id, wic)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
elif name.startswith("wic") and value == None:
|
||||||
|
wic_slot_id = int(name[-1])
|
||||||
|
if router.slots[0].wics and router.slots[0].wics[wic_slot_id]:
|
||||||
|
router.uninstall_wic(wic_slot_id)
|
||||||
|
|
||||||
|
# Update the ghost IOS file in case the RAM size has changed
|
||||||
|
if self._hypervisor_manager.ghost_ios_support:
|
||||||
|
self.set_ghost_ios(router)
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.allocate_udp_port")
|
||||||
|
def vm_allocate_udp_port(self, request):
|
||||||
|
"""
|
||||||
|
Allocates a UDP port in order to create an UDP NIO.
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# allocate a new UDP port
|
||||||
|
response = self.allocate_udp_port(router)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_response(response)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.add_nio")
|
||||||
|
def vm_add_nio(self, request):
|
||||||
|
"""
|
||||||
|
Adds an NIO (Network Input/Output) for a VM (router).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
|
||||||
|
slot = request["slot"]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
print(request)
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = self.create_nio(router, request)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
router.slot_add_nio_binding(slot, port, nio)
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
||||||
|
|
||||||
|
@IModule.route("dynamips.vm.delete_nio")
|
||||||
|
def vm_delete_nio(self, request):
|
||||||
|
"""
|
||||||
|
Deletes an NIO (Network Input/Output).
|
||||||
|
|
||||||
|
:param request: JSON request
|
||||||
|
"""
|
||||||
|
|
||||||
|
#TODO: JSON schema validation for the request
|
||||||
|
log.debug("received request {}".format(request))
|
||||||
|
router_id = request["id"]
|
||||||
|
router = self._routers[router_id]
|
||||||
|
slot = request["slot"]
|
||||||
|
port = request["port"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
nio = router.slot_remove_nio_binding(slot, port)
|
||||||
|
nio.delete()
|
||||||
|
except DynamipsError as e:
|
||||||
|
self.send_custom_error(str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
# for now send back the original request
|
||||||
|
self.send_response(request)
|
@ -31,3 +31,7 @@ class DynamipsError(Exception):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
||||||
return self._message
|
return self._message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
return self._message
|
||||||
|
@ -21,6 +21,7 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L46
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
import errno
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
from .dynamips_error import DynamipsError
|
from .dynamips_error import DynamipsError
|
||||||
@ -54,6 +55,7 @@ class DynamipsHypervisor(object):
|
|||||||
self._baseconsole = 2000
|
self._baseconsole = 2000
|
||||||
self._baseaux = 2100
|
self._baseaux = 2100
|
||||||
self._baseudp = 10000
|
self._baseudp = 10000
|
||||||
|
self._current_udp_port = self._baseudp
|
||||||
self._version = "N/A"
|
self._version = "N/A"
|
||||||
self._timeout = 30
|
self._timeout = 30
|
||||||
self._socket = None
|
self._socket = None
|
||||||
@ -145,7 +147,7 @@ class DynamipsHypervisor(object):
|
|||||||
@working_dir.setter
|
@working_dir.setter
|
||||||
def working_dir(self, working_dir):
|
def working_dir(self, working_dir):
|
||||||
"""
|
"""
|
||||||
Set the working directory for this hypervisor.
|
Sets the working directory for this hypervisor.
|
||||||
|
|
||||||
:param working_dir: path to the working directory
|
:param working_dir: path to the working directory
|
||||||
"""
|
"""
|
||||||
@ -198,7 +200,7 @@ class DynamipsHypervisor(object):
|
|||||||
@devices.setter
|
@devices.setter
|
||||||
def devices(self, devices):
|
def devices(self, devices):
|
||||||
"""
|
"""
|
||||||
Set the list of devices managed by this hypervisor instance.
|
Sets the list of devices managed by this hypervisor instance.
|
||||||
This method is for internal use.
|
This method is for internal use.
|
||||||
|
|
||||||
:param devices: a list of device objects
|
:param devices: a list of device objects
|
||||||
@ -219,7 +221,7 @@ class DynamipsHypervisor(object):
|
|||||||
@baseconsole.setter
|
@baseconsole.setter
|
||||||
def baseconsole(self, baseconsole):
|
def baseconsole(self, baseconsole):
|
||||||
"""
|
"""
|
||||||
Set the base console TCP port for this hypervisor.
|
Sets the base console TCP port for this hypervisor.
|
||||||
|
|
||||||
:param baseconsole: base console value (integer)
|
:param baseconsole: base console value (integer)
|
||||||
"""
|
"""
|
||||||
@ -239,7 +241,7 @@ class DynamipsHypervisor(object):
|
|||||||
@baseaux.setter
|
@baseaux.setter
|
||||||
def baseaux(self, baseaux):
|
def baseaux(self, baseaux):
|
||||||
"""
|
"""
|
||||||
Set the base auxiliary TCP port for this hypervisor.
|
Sets the base auxiliary TCP port for this hypervisor.
|
||||||
|
|
||||||
:param baseaux: base auxiliary port value (integer)
|
:param baseaux: base auxiliary port value (integer)
|
||||||
"""
|
"""
|
||||||
@ -259,12 +261,16 @@ class DynamipsHypervisor(object):
|
|||||||
@baseudp.setter
|
@baseudp.setter
|
||||||
def baseudp(self, baseudp):
|
def baseudp(self, baseudp):
|
||||||
"""
|
"""
|
||||||
Set the next open UDP port for NIOs for this hypervisor.
|
Sets the next open UDP port for NIOs for this hypervisor.
|
||||||
|
|
||||||
:param baseudp: base UDP port value (integer)
|
:param baseudp: base UDP port value (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._baseudp = baseudp
|
self._baseudp = baseudp
|
||||||
|
self._current_udp_port = self._baseudp
|
||||||
|
|
||||||
|
#FIXME
|
||||||
|
log.info("hypervisor a new base UDP {}".format(self._baseudp))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ghosts(self):
|
def ghosts(self):
|
||||||
@ -294,7 +300,7 @@ class DynamipsHypervisor(object):
|
|||||||
:returns: JIT sharing groups dict (image_name -> group number)
|
:returns: JIT sharing groups dict (image_name -> group number)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._ghosts
|
return self._jitsharing_groups
|
||||||
|
|
||||||
def add_jitsharing_group(self, image_name, group_number):
|
def add_jitsharing_group(self, image_name, group_number):
|
||||||
"""
|
"""
|
||||||
@ -326,6 +332,42 @@ class DynamipsHypervisor(object):
|
|||||||
|
|
||||||
return self._port
|
return self._port
|
||||||
|
|
||||||
|
def allocate_udp_port(self, max_port=100):
|
||||||
|
"""
|
||||||
|
Allocates a new UDP port for creating an UDP NIO.
|
||||||
|
|
||||||
|
:param max_port: maximum number of port to scan in
|
||||||
|
order to find one available for use.
|
||||||
|
|
||||||
|
:returns: port number (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
#FIXME: better check for IPv6
|
||||||
|
start_port = self._current_udp_port
|
||||||
|
print("start port = {}".format(start_port))
|
||||||
|
end_port = start_port + max_port
|
||||||
|
for port in range(start_port, end_port):
|
||||||
|
print(port)
|
||||||
|
if port > end_port:
|
||||||
|
raise DynamipsError("Could not find a free port between {0} and {1}".format(start_port, max_port))
|
||||||
|
try:
|
||||||
|
if self.host.__contains__(':'):
|
||||||
|
# IPv6 address support
|
||||||
|
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||||
|
else:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
# the port is available if bind is a success
|
||||||
|
s.bind((self._host, port))
|
||||||
|
#FIXME: increment?
|
||||||
|
self._current_udp_port += 1
|
||||||
|
print("current port = {}".format(self._current_udp_port))
|
||||||
|
return port
|
||||||
|
except socket.error as e:
|
||||||
|
if e.errno == errno.EADDRINUSE: # socket already in use
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise DynamipsError("UDP port allocation: {}".format(e))
|
||||||
|
|
||||||
def send_raw(self, string):
|
def send_raw(self, string):
|
||||||
"""
|
"""
|
||||||
Sends a raw command to this hypervisor. Use sparingly.
|
Sends a raw command to this hypervisor. Use sparingly.
|
||||||
|
@ -20,6 +20,7 @@ Represents a Dynamips hypervisor and starts/stops the associated Dynamips proces
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
@path.setter
|
@path.setter
|
||||||
def path(self, path):
|
def path(self, path):
|
||||||
"""
|
"""
|
||||||
Set the path to the Dynamips executable.
|
Sets the path to the Dynamips executable.
|
||||||
|
|
||||||
:param path: path to Dynamips
|
:param path: path to Dynamips
|
||||||
"""
|
"""
|
||||||
@ -102,7 +103,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
@port.setter
|
@port.setter
|
||||||
def port(self, port):
|
def port(self, port):
|
||||||
"""
|
"""
|
||||||
Set the port used to start the Dynamips hypervisor.
|
Sets the port used to start the Dynamips hypervisor.
|
||||||
|
|
||||||
:param port: port number (integer)
|
:param port: port number (integer)
|
||||||
"""
|
"""
|
||||||
@ -122,7 +123,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
@host.setter
|
@host.setter
|
||||||
def host(self, host):
|
def host(self, host):
|
||||||
"""
|
"""
|
||||||
Set the host (binding) used to start the Dynamips hypervisor.
|
Sets the host (binding) used to start the Dynamips hypervisor.
|
||||||
|
|
||||||
:param host: host/address (string)
|
:param host: host/address (string)
|
||||||
"""
|
"""
|
||||||
@ -142,7 +143,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
@workingdir.setter
|
@workingdir.setter
|
||||||
def workingdir(self, workingdir):
|
def workingdir(self, workingdir):
|
||||||
"""
|
"""
|
||||||
Set the working directory used to start the Dynamips hypervisor.
|
Sets the working directory used to start the Dynamips hypervisor.
|
||||||
|
|
||||||
:param workingdir: path to a working directory
|
:param workingdir: path to a working directory
|
||||||
"""
|
"""
|
||||||
@ -163,7 +164,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
@image_ref.setter
|
@image_ref.setter
|
||||||
def image_ref(self, ios_image_name):
|
def image_ref(self, ios_image_name):
|
||||||
"""
|
"""
|
||||||
Set the reference IOS image name
|
Sets the reference IOS image name
|
||||||
(used by the hypervisor manager for load-balancing purposes).
|
(used by the hypervisor manager for load-balancing purposes).
|
||||||
|
|
||||||
:param ios_image_name: image reference name
|
:param ios_image_name: image reference name
|
||||||
@ -230,8 +231,13 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
|
DynamipsHypervisor.stop(self)
|
||||||
logger.info("Stopping Dynamips PID={}".format(self._process.pid))
|
logger.info("Stopping Dynamips PID={}".format(self._process.pid))
|
||||||
|
# give some time for the hypervisor to properly stop.
|
||||||
|
# time to delete UNIX NIOs for instance.
|
||||||
|
time.sleep(0.01)
|
||||||
self._process.kill()
|
self._process.kill()
|
||||||
|
self._process.wait()
|
||||||
|
|
||||||
def read_stdout(self):
|
def read_stdout(self):
|
||||||
"""
|
"""
|
||||||
|
@ -45,27 +45,29 @@ class HypervisorManager(object):
|
|||||||
path,
|
path,
|
||||||
workingdir,
|
workingdir,
|
||||||
host='127.0.0.1',
|
host='127.0.0.1',
|
||||||
base_port=7200,
|
base_hypervisor_port=7200,
|
||||||
base_console=2000,
|
base_console_port=2000,
|
||||||
base_aux=3000,
|
base_aux_port=3000,
|
||||||
base_udp=10000):
|
base_udp_port=10000):
|
||||||
|
|
||||||
self._hypervisors = []
|
self._hypervisors = []
|
||||||
self._path = path
|
self._path = path
|
||||||
self._workingdir = workingdir
|
self._workingdir = workingdir
|
||||||
self._base_port = base_port
|
|
||||||
self._current_port = self._base_port
|
|
||||||
self._base_console = base_console
|
|
||||||
self._base_aux = base_aux
|
|
||||||
self._base_udp = base_udp
|
|
||||||
self._host = host
|
self._host = host
|
||||||
self._clean_workingdir = False
|
self._base_hypervisor_port = base_hypervisor_port
|
||||||
self._ghost_ios = True
|
self._current_port = self._base_hypervisor_port
|
||||||
self._mmap = True
|
self._base_console_port = base_console_port
|
||||||
self._jit_sharing = False
|
self._base_aux_port = base_aux_port
|
||||||
self._sparsemem = True
|
self._base_udp_port = base_udp_port
|
||||||
|
self._current_base_udp_port = self._base_udp_port
|
||||||
|
self._udp_incrementation_per_hypervisor = 100
|
||||||
|
self._ghost_ios_support = True
|
||||||
|
self._mmap_support = True
|
||||||
|
self._jit_sharing_support = False
|
||||||
|
self._sparse_memory_support = True
|
||||||
|
self._allocate_hypervisor_per_device = True
|
||||||
self._memory_usage_limit_per_hypervisor = 1024
|
self._memory_usage_limit_per_hypervisor = 1024
|
||||||
self._group_ios_per_hypervisor = True
|
self._allocate_hypervisor_per_ios_image = True
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""
|
"""
|
||||||
@ -84,6 +86,263 @@ class HypervisorManager(object):
|
|||||||
|
|
||||||
return self._hypervisors
|
return self._hypervisors
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
"""
|
||||||
|
Returns the Dynamips path.
|
||||||
|
|
||||||
|
:returns: path to Dynamips
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._path
|
||||||
|
|
||||||
|
@path.setter
|
||||||
|
def path(self, path):
|
||||||
|
"""
|
||||||
|
Set a new Dynamips path.
|
||||||
|
|
||||||
|
:param path: path to Dynamips
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._path = path
|
||||||
|
log.info("Dynamips path set to {}".format(self._path))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def workingdir(self):
|
||||||
|
"""
|
||||||
|
Returns the Dynamips working directory path.
|
||||||
|
|
||||||
|
:returns: path to Dynamips working directory
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._workingdir
|
||||||
|
|
||||||
|
@workingdir.setter
|
||||||
|
def workingdir(self, workingdir):
|
||||||
|
"""
|
||||||
|
Sets a new path to the Dynamips working directory.
|
||||||
|
|
||||||
|
:param workingdir: path to Dynamips working directory
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._workingdir = workingdir
|
||||||
|
log.info("working directory set to {}".format(self._workingdir))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_hypervisor_port(self):
|
||||||
|
"""
|
||||||
|
Returns the base hypervisor port.
|
||||||
|
|
||||||
|
:returns: base hypervisor port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._base_hypervisor_port
|
||||||
|
|
||||||
|
@base_hypervisor_port.setter
|
||||||
|
def base_hypervisor_port(self, base_hypervisor_port):
|
||||||
|
"""
|
||||||
|
Set a new base hypervisor port.
|
||||||
|
|
||||||
|
:param base_hypervisor_port: base hypervisor port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._base_hypervisor_port != base_hypervisor_port:
|
||||||
|
self._base_hypervisor_port = base_hypervisor_port
|
||||||
|
self._current_port = self._base_hypervisor_port
|
||||||
|
log.info("base hypervisor port set to {}".format(self._base_hypervisor_port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_console_port(self):
|
||||||
|
"""
|
||||||
|
Returns the base console port.
|
||||||
|
|
||||||
|
:returns: base console port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._base_console_port
|
||||||
|
|
||||||
|
@base_console_port.setter
|
||||||
|
def base_console_port(self, base_console_port):
|
||||||
|
"""
|
||||||
|
Set a new base console port.
|
||||||
|
|
||||||
|
:param base_console_port: base console port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._base_console_port != base_console_port:
|
||||||
|
self._base_console_port = base_console_port
|
||||||
|
log.info("base console port set to {}".format(self._base_console_port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_aux_port(self):
|
||||||
|
"""
|
||||||
|
Returns the base auxiliary console port.
|
||||||
|
|
||||||
|
:returns: base auxiliary console port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._base_aux_port
|
||||||
|
|
||||||
|
@base_aux_port.setter
|
||||||
|
def base_aux_port(self, base_aux_port):
|
||||||
|
"""
|
||||||
|
Set a new base auxiliary console port.
|
||||||
|
|
||||||
|
:param base_aux_port: base auxiliary console port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._base_aux_port != base_aux_port:
|
||||||
|
self._base_aux_port = base_aux_port
|
||||||
|
log.info("base aux port set to {}".format(self._base_aux_port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_udp_port(self):
|
||||||
|
"""
|
||||||
|
Returns the base UDP port.
|
||||||
|
|
||||||
|
:returns: base UDP port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._base_udp_port
|
||||||
|
|
||||||
|
@base_udp_port.setter
|
||||||
|
def base_udp_port(self, base_udp_port):
|
||||||
|
"""
|
||||||
|
Set a new base UDP port.
|
||||||
|
|
||||||
|
:param base_udp_port: base UDP port (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._base_udp_port != base_udp_port:
|
||||||
|
self._base_udp_port = base_udp_port
|
||||||
|
self._current_base_udp_port = self._base_udp_port
|
||||||
|
log.info("base UDP port set to {}".format(self._base_udp_port))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ghost_ios_support(self):
|
||||||
|
"""
|
||||||
|
Returns either ghost IOS is activated or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._ghost_ios_support
|
||||||
|
|
||||||
|
@ghost_ios_support.setter
|
||||||
|
def ghost_ios_support(self, ghost_ios_support):
|
||||||
|
"""
|
||||||
|
Sets ghost IOS support.
|
||||||
|
|
||||||
|
:param ghost_ios_support: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._ghost_ios_support != ghost_ios_support:
|
||||||
|
self._ghost_ios_support = ghost_ios_support
|
||||||
|
if ghost_ios_support:
|
||||||
|
log.info("ghost IOS support enabled")
|
||||||
|
else:
|
||||||
|
log.info("ghost IOS support disabled")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mmap_support(self):
|
||||||
|
"""
|
||||||
|
Returns either mmap is activated or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._mmap_support
|
||||||
|
|
||||||
|
@mmap_support.setter
|
||||||
|
def mmap_support(self, mmap_support):
|
||||||
|
"""
|
||||||
|
Sets mmap support.
|
||||||
|
|
||||||
|
:param mmap_support: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._mmap_support != mmap_support:
|
||||||
|
self._mmap_support = mmap_support
|
||||||
|
if mmap_support:
|
||||||
|
log.info("mmap support enabled")
|
||||||
|
else:
|
||||||
|
log.info("mmap support disabled")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sparse_memory_support(self):
|
||||||
|
"""
|
||||||
|
Returns either sparse memory is activated or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._sparse_memory_support
|
||||||
|
|
||||||
|
@sparse_memory_support.setter
|
||||||
|
def sparse_memory_support(self, sparse_memory_support):
|
||||||
|
"""
|
||||||
|
Sets sparse memory support.
|
||||||
|
|
||||||
|
:param sparse_memory_support: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._sparse_memory_support != sparse_memory_support:
|
||||||
|
self._sparse_memory_support = sparse_memory_support
|
||||||
|
if sparse_memory_support:
|
||||||
|
log.info("sparse memory support enabled")
|
||||||
|
else:
|
||||||
|
log.info("sparse memory support disabled")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def jit_sharing_support(self):
|
||||||
|
"""
|
||||||
|
Returns either JIT sharing is activated or not.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._jit_sharing_support
|
||||||
|
|
||||||
|
@jit_sharing_support.setter
|
||||||
|
def jit_sharing_support(self, jit_sharing_support):
|
||||||
|
"""
|
||||||
|
Sets JIT sharing support.
|
||||||
|
|
||||||
|
:param jit_sharing_support: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._jit_sharing_support != jit_sharing_support:
|
||||||
|
self._jit_sharing_support = jit_sharing_support
|
||||||
|
if jit_sharing_support:
|
||||||
|
log.info("JIT sharing support enabled")
|
||||||
|
else:
|
||||||
|
log.info("JIT sharing support disabled")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def allocate_hypervisor_per_device(self):
|
||||||
|
"""
|
||||||
|
Returns either an hypervisor is created for each device.
|
||||||
|
|
||||||
|
:returns: True or False
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._allocate_hypervisor_per_device
|
||||||
|
|
||||||
|
@allocate_hypervisor_per_device.setter
|
||||||
|
def allocate_hypervisor_per_device(self, value):
|
||||||
|
"""
|
||||||
|
Sets if an hypervisor is created for each device.
|
||||||
|
|
||||||
|
:param value: True or False
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._allocate_hypervisor_per_device != value:
|
||||||
|
self._allocate_hypervisor_per_device = value
|
||||||
|
if value:
|
||||||
|
log.info("allocating an hypervisor per device enabled")
|
||||||
|
else:
|
||||||
|
log.info("allocating an hypervisor per device disabled")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def memory_usage_limit_per_hypervisor(self):
|
def memory_usage_limit_per_hypervisor(self):
|
||||||
"""
|
"""
|
||||||
@ -97,15 +356,17 @@ class HypervisorManager(object):
|
|||||||
@memory_usage_limit_per_hypervisor.setter
|
@memory_usage_limit_per_hypervisor.setter
|
||||||
def memory_usage_limit_per_hypervisor(self, memory_limit):
|
def memory_usage_limit_per_hypervisor(self, memory_limit):
|
||||||
"""
|
"""
|
||||||
Set the memory usage limit per hypervisor
|
Sets the memory usage limit per hypervisor
|
||||||
|
|
||||||
:param memory_limit: memory limit value (integer)
|
:param memory_limit: memory limit value (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._memory_usage_limit_per_hypervisor = memory_limit
|
if self._memory_usage_limit_per_hypervisor != memory_limit:
|
||||||
|
self._memory_usage_limit_per_hypervisor = memory_limit
|
||||||
|
log.info("memory usage limit per hypervisor set to {}".format(memory_limit))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def group_ios_per_hypervisor(self):
|
def allocate_hypervisor_per_ios_image(self):
|
||||||
"""
|
"""
|
||||||
Returns if router are grouped per hypervisor
|
Returns if router are grouped per hypervisor
|
||||||
based on their IOS image.
|
based on their IOS image.
|
||||||
@ -113,18 +374,23 @@ class HypervisorManager(object):
|
|||||||
:returns: True or False
|
:returns: True or False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._group_ios_per_hypervisor
|
return self._allocate_hypervisor_per_ios_image
|
||||||
|
|
||||||
@group_ios_per_hypervisor.setter
|
@allocate_hypervisor_per_ios_image.setter
|
||||||
def group_ios_per_hypervisor(self, value):
|
def allocate_hypervisor_per_ios_image(self, value):
|
||||||
"""
|
"""
|
||||||
Set if router are grouped per hypervisor
|
Sets if routers are grouped per hypervisor
|
||||||
based on their IOS image.
|
based on their IOS image.
|
||||||
|
|
||||||
:param value: True or False
|
:param value: True or False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._group_ios_per_hypervisor = value
|
if self._allocate_hypervisor_per_ios_image != value:
|
||||||
|
self._allocate_hypervisor_per_ios_image = value
|
||||||
|
if value:
|
||||||
|
log.info("allocating an hypervisor per IOS image enabled")
|
||||||
|
else:
|
||||||
|
log.info("allocating an hypervisor per IOS image disabled")
|
||||||
|
|
||||||
def wait_for_hypervisor(self, host, port, timeout=10):
|
def wait_for_hypervisor(self, host, port, timeout=10):
|
||||||
"""
|
"""
|
||||||
@ -172,6 +438,10 @@ class HypervisorManager(object):
|
|||||||
log.info("hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
|
log.info("hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
|
||||||
|
|
||||||
hypervisor.connect()
|
hypervisor.connect()
|
||||||
|
hypervisor.baseconsole = self._base_console_port
|
||||||
|
hypervisor.baseaux = self._base_aux_port
|
||||||
|
hypervisor.baseudp = self._current_base_udp_port
|
||||||
|
self._current_base_udp_port += self._udp_incrementation_per_hypervisor
|
||||||
self._hypervisors.append(hypervisor)
|
self._hypervisors.append(hypervisor)
|
||||||
self._current_port += 1
|
self._current_port += 1
|
||||||
return hypervisor
|
return hypervisor
|
||||||
@ -187,16 +457,21 @@ class HypervisorManager(object):
|
|||||||
:returns: the allocated hypervisor object
|
:returns: the allocated hypervisor object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for hypervisor in self._hypervisors:
|
# allocate an hypervisor for each router by default
|
||||||
if self._group_ios_per_hypervisor and hypervisor.image_ref != router_ios_image:
|
if not self._allocate_hypervisor_per_device:
|
||||||
continue
|
for hypervisor in self._hypervisors:
|
||||||
if (hypervisor.memory_load + router_ram) <= self._memory_usage_limit_per_hypervisor:
|
if self._allocate_hypervisor_per_ios_image:
|
||||||
current_memory_load = hypervisor.memory_load
|
if not hypervisor.image_ref:
|
||||||
hypervisor.increase_memory_load(router_ram)
|
hypervisor.image_ref = router_ios_image
|
||||||
log.info("allocating existing hypervisor {}:{}, RAM={}+{}".format(hypervisor.host,
|
elif hypervisor.image_ref != router_ios_image:
|
||||||
hypervisor.port,
|
continue
|
||||||
current_memory_load,
|
if (hypervisor.memory_load + router_ram) <= self._memory_usage_limit_per_hypervisor:
|
||||||
router_ram))
|
current_memory_load = hypervisor.memory_load
|
||||||
|
hypervisor.increase_memory_load(router_ram)
|
||||||
|
log.info("allocating existing hypervisor {}:{}, RAM={}+{}".format(hypervisor.host,
|
||||||
|
hypervisor.port,
|
||||||
|
current_memory_load,
|
||||||
|
router_ram))
|
||||||
return hypervisor
|
return hypervisor
|
||||||
|
|
||||||
hypervisor = self.start_new_hypervisor()
|
hypervisor = self.start_new_hypervisor()
|
||||||
@ -226,6 +501,22 @@ class HypervisorManager(object):
|
|||||||
hypervisor.stop()
|
hypervisor.stop()
|
||||||
self._hypervisors.remove(hypervisor)
|
self._hypervisors.remove(hypervisor)
|
||||||
|
|
||||||
|
def allocate_hypervisor_for_switch(self):
|
||||||
|
"""
|
||||||
|
Allocates a Dynamips hypervisor for a specific switch
|
||||||
|
|
||||||
|
:returns: the allocated hypervisor object
|
||||||
|
"""
|
||||||
|
|
||||||
|
# For now always allocate the first hypervisor available,
|
||||||
|
# in the future we could randomly allocate.
|
||||||
|
|
||||||
|
if self._hypervisors:
|
||||||
|
return self._hypervisors[0]
|
||||||
|
|
||||||
|
# no hypervisor, let's start one!
|
||||||
|
return self.start_new_hypervisor()
|
||||||
|
|
||||||
def stop_all_hypervisors(self):
|
def stop_all_hypervisors(self):
|
||||||
"""
|
"""
|
||||||
Stops all hypervisors.
|
Stops all hypervisors.
|
||||||
@ -233,3 +524,4 @@ class HypervisorManager(object):
|
|||||||
|
|
||||||
for hypervisor in self._hypervisors:
|
for hypervisor in self._hypervisors:
|
||||||
hypervisor.stop()
|
hypervisor.stop()
|
||||||
|
self._hypervisors = []
|
||||||
|
@ -22,6 +22,9 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L451
|
|||||||
|
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO(object):
|
class NIO(object):
|
||||||
"""
|
"""
|
||||||
@ -55,6 +58,7 @@ class NIO(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("nio delete {}".format(self._name))
|
self._hypervisor.send("nio delete {}".format(self._name))
|
||||||
|
log.info("NIO {name} has been deleted".format(name=self._name))
|
||||||
|
|
||||||
def rename(self, new_name):
|
def rename(self, new_name):
|
||||||
"""
|
"""
|
||||||
@ -65,6 +69,9 @@ class NIO(object):
|
|||||||
|
|
||||||
self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_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
|
self._name = new_name
|
||||||
|
|
||||||
def debug(self, debug):
|
def debug(self, debug):
|
||||||
@ -197,7 +204,7 @@ class NIO(object):
|
|||||||
|
|
||||||
def set_bandwidth(self, bandwidth):
|
def set_bandwidth(self, bandwidth):
|
||||||
"""
|
"""
|
||||||
Set bandwidth constraint.
|
Sets bandwidth constraint.
|
||||||
|
|
||||||
:param bandwidth: bandwidth integer value (in Kb/s)
|
:param bandwidth: bandwidth integer value (in Kb/s)
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for FIFO NIOs.
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_FIFO(NIO):
|
class NIO_FIFO(NIO):
|
||||||
"""
|
"""
|
||||||
@ -42,6 +45,16 @@ class NIO_FIFO(NIO):
|
|||||||
|
|
||||||
self._hypervisor.send("nio create_fifo {}".format(self._name))
|
self._hypervisor.send("nio create_fifo {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("NIO FIFO {name} created.".format(name=self._name))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
def crossconnect(self, nio):
|
def crossconnect(self, nio):
|
||||||
"""
|
"""
|
||||||
Establishes a cross-connect between this FIFO NIO and another one.
|
Establishes a cross-connect between this FIFO NIO and another one.
|
||||||
@ -51,3 +64,5 @@ class NIO_FIFO(NIO):
|
|||||||
|
|
||||||
self._hypervisor.send("nio crossconnect_fifo {name} {nio}".format(name=self._name,
|
self._hypervisor.send("nio crossconnect_fifo {name} {nio}".format(name=self._name,
|
||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
|
log.info("NIO FIFO {name} crossconnected with {nio_name}.".format(name=self._name, nio_name=nio.name))
|
||||||
|
@ -21,6 +21,9 @@ Interface for generic Ethernet NIOs (PCAP library).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_GenericEthernet(NIO):
|
class NIO_GenericEthernet(NIO):
|
||||||
"""
|
"""
|
||||||
@ -45,6 +48,17 @@ class NIO_GenericEthernet(NIO):
|
|||||||
self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name,
|
self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name,
|
||||||
eth_device=ethernet_device))
|
eth_device=ethernet_device))
|
||||||
|
|
||||||
|
log.info("NIO Generic Ethernet {name} created with device {device}".format(name=self._name,
|
||||||
|
device=ethernet_device))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ethernet_device(self):
|
def ethernet_device(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for Linux Ethernet NIOs (Linux only).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_LinuxEthernet(NIO):
|
class NIO_LinuxEthernet(NIO):
|
||||||
"""
|
"""
|
||||||
@ -45,6 +48,17 @@ class NIO_LinuxEthernet(NIO):
|
|||||||
self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name,
|
self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name,
|
||||||
eth_device=ethernet_device))
|
eth_device=ethernet_device))
|
||||||
|
|
||||||
|
log.info("NIO Linux Ethernet {name} created with device {device}".format(name=self._name,
|
||||||
|
device=ethernet_device))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ethernet_device(self):
|
def ethernet_device(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for multicast NIOs.
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_Mcast(NIO):
|
class NIO_Mcast(NIO):
|
||||||
"""
|
"""
|
||||||
@ -49,6 +52,18 @@ class NIO_Mcast(NIO):
|
|||||||
mgroup=group,
|
mgroup=group,
|
||||||
mport=port))
|
mport=port))
|
||||||
|
|
||||||
|
log.info("NIO Multicast {name} created with mgroup={group}, mport={port}".format(name=self._name,
|
||||||
|
group=group,
|
||||||
|
port=port))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def group(self):
|
def group(self):
|
||||||
"""
|
"""
|
||||||
@ -82,7 +97,7 @@ class NIO_Mcast(NIO):
|
|||||||
@ttl.setter
|
@ttl.setter
|
||||||
def ttl(self, ttl):
|
def ttl(self, ttl):
|
||||||
"""
|
"""
|
||||||
Set the TTL for the multicast address
|
Sets the TTL for the multicast address
|
||||||
|
|
||||||
:param ttl: TTL value
|
:param ttl: TTL value
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for dummy NIOs (mostly for tests).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_Null(NIO):
|
class NIO_Null(NIO):
|
||||||
"""
|
"""
|
||||||
@ -41,3 +44,12 @@ class NIO_Null(NIO):
|
|||||||
self._name = 'nio_null' + str(self._id)
|
self._name = 'nio_null' + str(self._id)
|
||||||
|
|
||||||
self._hypervisor.send("nio create_null {}".format(self._name))
|
self._hypervisor.send("nio create_null {}".format(self._name))
|
||||||
|
log.info("NIO NULL {name} created.".format(name=self._name))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
@ -21,6 +21,9 @@ Interface for TAP NIOs (UNIX based OSes only).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_TAP(NIO):
|
class NIO_TAP(NIO):
|
||||||
"""
|
"""
|
||||||
@ -45,6 +48,17 @@ class NIO_TAP(NIO):
|
|||||||
self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name,
|
self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name,
|
||||||
tap=tap_device))
|
tap=tap_device))
|
||||||
|
|
||||||
|
log.info("NIO TAP {name} created with device {device}".format(name=self._name,
|
||||||
|
device=tap_device))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tap_device(self):
|
def tap_device(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for UDP NIOs.
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_UDP(NIO):
|
class NIO_UDP(NIO):
|
||||||
"""
|
"""
|
||||||
@ -51,6 +54,19 @@ class NIO_UDP(NIO):
|
|||||||
rhost=rhost,
|
rhost=rhost,
|
||||||
rport=rport))
|
rport=rport))
|
||||||
|
|
||||||
|
log.info("NIO UDP {name} created with lport={lport}, rhost={rhost}, rport={rport}".format(name=self._name,
|
||||||
|
lport=lport,
|
||||||
|
rhost=rhost,
|
||||||
|
rport=rport))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lport(self):
|
def lport(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for automatic UDP NIOs.
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_UDP_auto(NIO):
|
class NIO_UDP_auto(NIO):
|
||||||
"""
|
"""
|
||||||
@ -48,9 +51,22 @@ class NIO_UDP_auto(NIO):
|
|||||||
laddr=laddr,
|
laddr=laddr,
|
||||||
lport_start=lport_start,
|
lport_start=lport_start,
|
||||||
lport_end=lport_end))[0])
|
lport_end=lport_end))[0])
|
||||||
|
|
||||||
|
log.info("NIO UDP AUTO {name} created with laddr={laddr}, lport_start={start}, lport_end={end}".format(name=self._name,
|
||||||
|
laddr=laddr,
|
||||||
|
start=lport_start,
|
||||||
|
end=lport_end))
|
||||||
self._raddr = None
|
self._raddr = None
|
||||||
self._rport = None
|
self._rport = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def laddr(self):
|
def laddr(self):
|
||||||
"""
|
"""
|
||||||
@ -104,3 +120,7 @@ class NIO_UDP_auto(NIO):
|
|||||||
rport=rport))
|
rport=rport))
|
||||||
self._raddr = raddr
|
self._raddr = raddr
|
||||||
self._rport = rport
|
self._rport = rport
|
||||||
|
|
||||||
|
log.info("NIO UDP AUTO {name} connected to {raddr}:{rport}".format(name=self._name,
|
||||||
|
raddr=raddr,
|
||||||
|
rport=rport))
|
||||||
|
@ -21,6 +21,9 @@ Interface for UNIX NIOs (Unix based OSes only).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_UNIX(NIO):
|
class NIO_UNIX(NIO):
|
||||||
"""
|
"""
|
||||||
@ -48,6 +51,18 @@ class NIO_UNIX(NIO):
|
|||||||
local=local_file,
|
local=local_file,
|
||||||
remote=remote_file))
|
remote=remote_file))
|
||||||
|
|
||||||
|
log.info("NIO UNIX {name} created with local file {local} and remote file {remote}".format(name=self._name,
|
||||||
|
local=local_file,
|
||||||
|
remote=remote_file))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def local_file(self):
|
def local_file(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,9 @@ Interface for VDE (Virtual Distributed Ethernet) NIOs (Unix based OSes only).
|
|||||||
|
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NIO_VDE(NIO):
|
class NIO_VDE(NIO):
|
||||||
"""
|
"""
|
||||||
@ -48,6 +51,18 @@ class NIO_VDE(NIO):
|
|||||||
control=control_file,
|
control=control_file,
|
||||||
local=local_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
|
@property
|
||||||
def control_file(self):
|
def control_file(self):
|
||||||
"""
|
"""
|
||||||
|
@ -23,6 +23,9 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ATMSwitch(object):
|
class ATMSwitch(object):
|
||||||
"""
|
"""
|
||||||
@ -32,15 +35,47 @@ class ATMSwitch(object):
|
|||||||
:param name: name for this switch
|
:param name: name for this switch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
_instance_count = 1
|
||||||
|
|
||||||
|
def __init__(self, hypervisor, name=None):
|
||||||
|
|
||||||
|
# create an unique ID
|
||||||
|
self._id = ATMSwitch._instance_count
|
||||||
|
ATMSwitch._instance_count += 1
|
||||||
|
|
||||||
|
# let's create a unique name if none has been chosen
|
||||||
|
if not name:
|
||||||
|
name = "ATM" + str(self._id)
|
||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
||||||
self._hypervisor.send("atmsw create {}".format(self._name))
|
self._hypervisor.send("atmsw create {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}] has been created".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
self._hypervisor.devices.append(self)
|
self._hypervisor.devices.append(self)
|
||||||
self._nios = {}
|
self._nios = {}
|
||||||
self._mapping = {}
|
self._mapping = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
Returns the unique ID for this ATM switch.
|
||||||
|
|
||||||
|
:returns: id (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""
|
"""
|
||||||
@ -100,6 +135,11 @@ class ATMSwitch(object):
|
|||||||
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
||||||
self._hypervisor.send("atmsw rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("atmsw rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_name))
|
new_name=new_name))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
new_name=new_name))
|
||||||
|
|
||||||
self._name = new_name
|
self._name = new_name
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
@ -108,8 +148,22 @@ class ATMSwitch(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("atmsw delete {}".format(self._name))
|
self._hypervisor.send("atmsw delete {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}] has been deleted".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
self._hypervisor.devices.remove(self)
|
self._hypervisor.devices.remove(self)
|
||||||
|
|
||||||
|
def has_port(self, port):
|
||||||
|
"""
|
||||||
|
Checks if a port exists on this ATM switch.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port in self._nios:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def add_nio(self, nio, port):
|
def add_nio(self, nio, port):
|
||||||
"""
|
"""
|
||||||
Adds a NIO as new port on ATM switch.
|
Adds a NIO as new port on ATM switch.
|
||||||
@ -121,6 +175,11 @@ class ATMSwitch(object):
|
|||||||
if port in self._nios:
|
if port in self._nios:
|
||||||
raise DynamipsError("Port {} isn't free".format(port))
|
raise DynamipsError("Port {} isn't free".format(port))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
self._nios[port] = nio
|
self._nios[port] = nio
|
||||||
|
|
||||||
def remove_nio(self, port):
|
def remove_nio(self, port):
|
||||||
@ -133,7 +192,14 @@ class ATMSwitch(object):
|
|||||||
if port not in self._nios:
|
if port not in self._nios:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port))
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
log.info("ATM switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
del self._nios[port]
|
del self._nios[port]
|
||||||
|
return nio
|
||||||
|
|
||||||
def map_vp(self, port1, vpi1, port2, vpi2):
|
def map_vp(self, port1, vpi1, port2, vpi2):
|
||||||
"""
|
"""
|
||||||
@ -159,6 +225,14 @@ class ATMSwitch(object):
|
|||||||
input_vpi=vpi1,
|
input_vpi=vpi1,
|
||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_vpi=vpi2))
|
output_vpi=vpi2))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: VPC from port {port1} VPI {vpi1} to port {port2} VPI {vpi2} created".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
vpi1=vpi1,
|
||||||
|
port2=port2,
|
||||||
|
vpi2=vpi2))
|
||||||
|
|
||||||
self._mapping[(port1, vpi1)] = (port2, vpi2)
|
self._mapping[(port1, vpi1)] = (port2, vpi2)
|
||||||
|
|
||||||
def unmap_vp(self, port1, vpi1, port2, vpi2):
|
def unmap_vp(self, port1, vpi1, port2, vpi2):
|
||||||
@ -185,6 +259,14 @@ class ATMSwitch(object):
|
|||||||
input_vpi=vpi1,
|
input_vpi=vpi1,
|
||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_vpi=vpi2))
|
output_vpi=vpi2))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: VPC from port {port1} VPI {vpi1} to port {port2} VPI {vpi2} deleted".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
vpi1=vpi1,
|
||||||
|
port2=port2,
|
||||||
|
vpi2=vpi2))
|
||||||
|
|
||||||
del self._mapping[(port1, vpi1)]
|
del self._mapping[(port1, vpi1)]
|
||||||
|
|
||||||
def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
||||||
@ -215,6 +297,16 @@ class ATMSwitch(object):
|
|||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_vpi=vpi2,
|
output_vpi=vpi2,
|
||||||
output_vci=vci2))
|
output_vci=vci2))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: VCC from port {port1} VPI {vpi1} VCI {vci1} to port {port2} VPI {vpi2} VCI {vci2} created".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
vpi1=vpi1,
|
||||||
|
vci1=vci1,
|
||||||
|
port2=port2,
|
||||||
|
vpi2=vpi2,
|
||||||
|
vci2=vci2))
|
||||||
|
|
||||||
self._mapping[(port1, vpi1, vci1)] = (port2, vpi2, vci2)
|
self._mapping[(port1, vpi1, vci1)] = (port2, vpi2, vci2)
|
||||||
|
|
||||||
def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
||||||
@ -245,4 +337,13 @@ class ATMSwitch(object):
|
|||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_vpi=vpi2,
|
output_vpi=vpi2,
|
||||||
output_vci=vci2))
|
output_vci=vci2))
|
||||||
|
|
||||||
|
log.info("ATM switch {name} [id={id}]: VCC from port {port1} VPI {vpi1} VCI {vci1} to port {port2} VPI {vpi2} VCI {vci2} deleted".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
vpi1=vpi1,
|
||||||
|
vci1=vci1,
|
||||||
|
port2=port2,
|
||||||
|
vpi2=vpi2,
|
||||||
|
vci2=vci2))
|
||||||
del self._mapping[(port1, vpi1, vci1)]
|
del self._mapping[(port1, vpi1, vci1)]
|
||||||
|
@ -88,6 +88,7 @@ class Bridge(object):
|
|||||||
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
||||||
self._hypervisor.send("nio_bridge rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("nio_bridge rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_name))
|
new_name=new_name))
|
||||||
|
|
||||||
self._name = new_name
|
self._name = new_name
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
@ -25,6 +25,9 @@ from .router import Router
|
|||||||
from ..adapters.c1700_mb_1fe import C1700_MB_1FE
|
from ..adapters.c1700_mb_1fe import C1700_MB_1FE
|
||||||
from ..adapters.c1700_mb_wic1 import C1700_MB_WIC1
|
from ..adapters.c1700_mb_wic1 import C1700_MB_WIC1
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C1700(Router):
|
class C1700(Router):
|
||||||
"""
|
"""
|
||||||
@ -37,7 +40,7 @@ class C1700(Router):
|
|||||||
1710 is not supported.
|
1710 is not supported.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name, chassis="1720"):
|
def __init__(self, hypervisor, name=None, chassis="1720"):
|
||||||
Router.__init__(self, hypervisor, name, platform="c1700")
|
Router.__init__(self, hypervisor, name, platform="c1700")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -54,6 +57,27 @@ class C1700(Router):
|
|||||||
|
|
||||||
self._setup_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}
|
||||||
|
|
||||||
|
# update the router defaults with the platform specific defaults
|
||||||
|
router_defaults.update(platform_defaults)
|
||||||
|
return router_defaults
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c1700 instances
|
Returns all c1700 instances
|
||||||
@ -65,7 +89,7 @@ class C1700(Router):
|
|||||||
|
|
||||||
def _setup_chassis(self):
|
def _setup_chassis(self):
|
||||||
"""
|
"""
|
||||||
Set up the router with the corresponding chassis
|
Sets up the router with the corresponding chassis
|
||||||
(create slots and insert default adapters).
|
(create slots and insert default adapters).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -91,7 +115,7 @@ class C1700(Router):
|
|||||||
@chassis.setter
|
@chassis.setter
|
||||||
def chassis(self, chassis):
|
def chassis(self, chassis):
|
||||||
"""
|
"""
|
||||||
Set the chassis.
|
Sets the chassis.
|
||||||
|
|
||||||
:param: chassis string:
|
:param: chassis string:
|
||||||
1720, 1721, 1750, 1751 or 1760
|
1720, 1721, 1750, 1751 or 1760
|
||||||
@ -99,6 +123,11 @@ class C1700(Router):
|
|||||||
|
|
||||||
self._hypervisor.send("c1700 set_chassis {name} {chassis}".format(name=self._name,
|
self._hypervisor.send("c1700 set_chassis {name} {chassis}".format(name=self._name,
|
||||||
chassis=chassis))
|
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._chassis = chassis
|
||||||
self._setup_chassis()
|
self._setup_chassis()
|
||||||
|
|
||||||
@ -115,11 +144,16 @@ class C1700(Router):
|
|||||||
@iomem.setter
|
@iomem.setter
|
||||||
def iomem(self, iomem):
|
def iomem(self, iomem):
|
||||||
"""
|
"""
|
||||||
Set I/O memory size for this router.
|
Sets I/O memory size for this router.
|
||||||
|
|
||||||
:param iomem: I/O memory size
|
:param iomem: I/O memory size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c1700 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c1700 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -27,6 +27,9 @@ from ..adapters.c2600_mb_2e import C2600_MB_2E
|
|||||||
from ..adapters.c2600_mb_1fe import C2600_MB_1FE
|
from ..adapters.c2600_mb_1fe import C2600_MB_1FE
|
||||||
from ..adapters.c2600_mb_2fe import C2600_MB_2FE
|
from ..adapters.c2600_mb_2fe import C2600_MB_2FE
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C2600(Router):
|
class C2600(Router):
|
||||||
"""
|
"""
|
||||||
@ -52,7 +55,7 @@ class C2600(Router):
|
|||||||
'2650XM': C2600_MB_1FE,
|
'2650XM': C2600_MB_1FE,
|
||||||
'2651XM': C2600_MB_2FE}
|
'2651XM': C2600_MB_2FE}
|
||||||
|
|
||||||
def __init__(self, hypervisor, name, chassis="2610"):
|
def __init__(self, hypervisor, name=None, chassis="2610"):
|
||||||
Router.__init__(self, hypervisor, name, platform="c2600")
|
Router.__init__(self, hypervisor, name, platform="c2600")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -69,6 +72,27 @@ class C2600(Router):
|
|||||||
|
|
||||||
self._setup_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):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c2600 instances
|
Returns all c2600 instances
|
||||||
@ -80,7 +104,7 @@ class C2600(Router):
|
|||||||
|
|
||||||
def _setup_chassis(self):
|
def _setup_chassis(self):
|
||||||
"""
|
"""
|
||||||
Set up the router with the corresponding chassis
|
Sets up the router with the corresponding chassis
|
||||||
(create slots and insert default adapters).
|
(create slots and insert default adapters).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -100,7 +124,7 @@ class C2600(Router):
|
|||||||
@chassis.setter
|
@chassis.setter
|
||||||
def chassis(self, chassis):
|
def chassis(self, chassis):
|
||||||
"""
|
"""
|
||||||
Set the chassis.
|
Sets the chassis.
|
||||||
|
|
||||||
:param: chassis string:
|
:param: chassis string:
|
||||||
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
||||||
@ -109,6 +133,10 @@ class C2600(Router):
|
|||||||
|
|
||||||
self._hypervisor.send("c2600 set_chassis {name} {chassis}".format(name=self._name,
|
self._hypervisor.send("c2600 set_chassis {name} {chassis}".format(name=self._name,
|
||||||
chassis=chassis))
|
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._chassis = chassis
|
||||||
self._setup_chassis()
|
self._setup_chassis()
|
||||||
|
|
||||||
@ -125,11 +153,16 @@ class C2600(Router):
|
|||||||
@iomem.setter
|
@iomem.setter
|
||||||
def iomem(self, iomem):
|
def iomem(self, iomem):
|
||||||
"""
|
"""
|
||||||
Set I/O memory size for this router.
|
Sets I/O memory size for this router.
|
||||||
|
|
||||||
:param iomem: I/O memory size
|
:param iomem: I/O memory size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c2600 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c2600 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -24,6 +24,9 @@ from __future__ import unicode_literals
|
|||||||
from .router import Router
|
from .router import Router
|
||||||
from ..adapters.gt96100_fe import GT96100_FE
|
from ..adapters.gt96100_fe import GT96100_FE
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C2691(Router):
|
class C2691(Router):
|
||||||
"""
|
"""
|
||||||
@ -33,7 +36,7 @@ class C2691(Router):
|
|||||||
:param name: name for this router
|
:param name: name for this router
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
def __init__(self, hypervisor, name=None):
|
||||||
Router.__init__(self, hypervisor, name, platform="c2691")
|
Router.__init__(self, hypervisor, name, platform="c2691")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -47,6 +50,26 @@ class C2691(Router):
|
|||||||
self._create_slots(2)
|
self._create_slots(2)
|
||||||
self._slots[0] = GT96100_FE()
|
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):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c2691 instances
|
Returns all c2691 instances
|
||||||
@ -69,11 +92,16 @@ class C2691(Router):
|
|||||||
@iomem.setter
|
@iomem.setter
|
||||||
def iomem(self, iomem):
|
def iomem(self, iomem):
|
||||||
"""
|
"""
|
||||||
Set I/O memory size for this router.
|
Sets I/O memory size for this router.
|
||||||
|
|
||||||
:param iomem: I/O memory size
|
:param iomem: I/O memory size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c2691 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c2691 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -24,6 +24,9 @@ from __future__ import unicode_literals
|
|||||||
from .router import Router
|
from .router import Router
|
||||||
from ..adapters.leopard_2fe import Leopard_2FE
|
from ..adapters.leopard_2fe import Leopard_2FE
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C3600(Router):
|
class C3600(Router):
|
||||||
"""
|
"""
|
||||||
@ -35,7 +38,7 @@ class C3600(Router):
|
|||||||
3620, 3640 or 3660 (default = 3640).
|
3620, 3640 or 3660 (default = 3640).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name, chassis="3640"):
|
def __init__(self, hypervisor, name=None, chassis="3640"):
|
||||||
Router.__init__(self, hypervisor, name, platform="c3600")
|
Router.__init__(self, hypervisor, name, platform="c3600")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -52,6 +55,27 @@ class C3600(Router):
|
|||||||
|
|
||||||
self._setup_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):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c3600 instances
|
Returns all c3600 instances
|
||||||
@ -63,7 +87,7 @@ class C3600(Router):
|
|||||||
|
|
||||||
def _setup_chassis(self):
|
def _setup_chassis(self):
|
||||||
"""
|
"""
|
||||||
Set up the router with the corresponding chassis
|
Sets up the router with the corresponding chassis
|
||||||
(create slots and insert default adapters).
|
(create slots and insert default adapters).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -88,13 +112,18 @@ class C3600(Router):
|
|||||||
@chassis.setter
|
@chassis.setter
|
||||||
def chassis(self, chassis):
|
def chassis(self, chassis):
|
||||||
"""
|
"""
|
||||||
Set the chassis.
|
Sets the chassis.
|
||||||
|
|
||||||
:param: chassis string: 3620, 3640 or 3660
|
:param: chassis string: 3620, 3640 or 3660
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c3600 set_chassis {name} {chassis}".format(name=self._name,
|
self._hypervisor.send("c3600 set_chassis {name} {chassis}".format(name=self._name,
|
||||||
chassis=chassis))
|
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._chassis = chassis
|
||||||
self._setup_chassis()
|
self._setup_chassis()
|
||||||
|
|
||||||
@ -118,4 +147,9 @@ class C3600(Router):
|
|||||||
|
|
||||||
self._hypervisor.send("c3600 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c3600 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -24,6 +24,9 @@ from __future__ import unicode_literals
|
|||||||
from .router import Router
|
from .router import Router
|
||||||
from ..adapters.gt96100_fe import GT96100_FE
|
from ..adapters.gt96100_fe import GT96100_FE
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C3725(Router):
|
class C3725(Router):
|
||||||
"""
|
"""
|
||||||
@ -33,7 +36,7 @@ class C3725(Router):
|
|||||||
:param name: name for this router
|
:param name: name for this router
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
def __init__(self, hypervisor, name=None):
|
||||||
Router.__init__(self, hypervisor, name, platform="c3725")
|
Router.__init__(self, hypervisor, name, platform="c3725")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -47,6 +50,26 @@ class C3725(Router):
|
|||||||
self._create_slots(3)
|
self._create_slots(3)
|
||||||
self._slots[0] = GT96100_FE()
|
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):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c3725 instances.
|
Returns all c3725 instances.
|
||||||
@ -69,11 +92,16 @@ class C3725(Router):
|
|||||||
@iomem.setter
|
@iomem.setter
|
||||||
def iomem(self, iomem):
|
def iomem(self, iomem):
|
||||||
"""
|
"""
|
||||||
Set I/O memory size for this router.
|
Sets I/O memory size for this router.
|
||||||
|
|
||||||
:param iomem: I/O memory size
|
:param iomem: I/O memory size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c3725 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c3725 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -24,6 +24,9 @@ from __future__ import unicode_literals
|
|||||||
from .router import Router
|
from .router import Router
|
||||||
from ..adapters.gt96100_fe import GT96100_FE
|
from ..adapters.gt96100_fe import GT96100_FE
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C3745(Router):
|
class C3745(Router):
|
||||||
"""
|
"""
|
||||||
@ -33,7 +36,7 @@ class C3745(Router):
|
|||||||
:param name: name for this router
|
:param name: name for this router
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
def __init__(self, hypervisor, name=None):
|
||||||
Router.__init__(self, hypervisor, name, platform="c3745")
|
Router.__init__(self, hypervisor, name, platform="c3745")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -47,6 +50,26 @@ class C3745(Router):
|
|||||||
self._create_slots(5)
|
self._create_slots(5)
|
||||||
self._slots[0] = GT96100_FE()
|
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):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c3745 instances.
|
Returns all c3745 instances.
|
||||||
@ -69,11 +92,16 @@ class C3745(Router):
|
|||||||
@iomem.setter
|
@iomem.setter
|
||||||
def iomem(self, iomem):
|
def iomem(self, iomem):
|
||||||
"""
|
"""
|
||||||
Set I/O memory size for this router.
|
Sets I/O memory size for this router.
|
||||||
|
|
||||||
:param iomem: I/O memory size
|
:param iomem: I/O memory size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c3745 set_iomem {name} {size}".format(name=self._name,
|
self._hypervisor.send("c3745 set_iomem {name} {size}".format(name=self._name,
|
||||||
size=iomem))
|
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
|
self._iomem = iomem
|
||||||
|
@ -20,13 +20,15 @@ Interface for Dynamips virtual Cisco 7200 instances module ("c7200")
|
|||||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L294
|
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L294
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
from .router import Router
|
from .router import Router
|
||||||
from ..adapters.c7200_io_2fe import C7200_IO_2FE
|
from ..adapters.c7200_io_2fe import C7200_IO_2FE
|
||||||
from ..adapters.c7200_io_ge_e import C7200_IO_GE_E
|
from ..adapters.c7200_io_ge_e import C7200_IO_GE_E
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class C7200(Router):
|
class C7200(Router):
|
||||||
"""
|
"""
|
||||||
@ -37,7 +39,7 @@ class C7200(Router):
|
|||||||
:param npe: default NPE
|
:param npe: default NPE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name, npe="npe-400"):
|
def __init__(self, hypervisor, name=None, npe="npe-400"):
|
||||||
Router.__init__(self, hypervisor, name, platform="c7200")
|
Router.__init__(self, hypervisor, name, platform="c7200")
|
||||||
|
|
||||||
# Set default values for this platform
|
# Set default values for this platform
|
||||||
@ -70,6 +72,27 @@ class C7200(Router):
|
|||||||
else:
|
else:
|
||||||
self._slots[0] = C7200_IO_2FE()
|
self._slots[0] = C7200_IO_2FE()
|
||||||
|
|
||||||
|
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}
|
||||||
|
|
||||||
|
# update the router defaults with the platform specific defaults
|
||||||
|
router_defaults.update(platform_defaults)
|
||||||
|
return router_defaults
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
Returns all c7200 instances.
|
Returns all c7200 instances.
|
||||||
@ -92,7 +115,7 @@ class C7200(Router):
|
|||||||
@npe.setter
|
@npe.setter
|
||||||
def npe(self, npe):
|
def npe(self, npe):
|
||||||
"""
|
"""
|
||||||
Set the NPE model.
|
Sets the NPE model.
|
||||||
|
|
||||||
:params npe: NPE model string (e.g. "npe-200")
|
:params npe: NPE model string (e.g. "npe-200")
|
||||||
NPE models are npe-100, npe-150, npe-175, npe-200,
|
NPE models are npe-100, npe-150, npe-175, npe-200,
|
||||||
@ -104,6 +127,11 @@ class C7200(Router):
|
|||||||
|
|
||||||
self._hypervisor.send("c7200 set_npe {name} {npe}".format(name=self._name,
|
self._hypervisor.send("c7200 set_npe {name} {npe}".format(name=self._name,
|
||||||
npe=npe))
|
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
|
self._npe = npe
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -119,13 +147,18 @@ class C7200(Router):
|
|||||||
@midplane.setter
|
@midplane.setter
|
||||||
def midplane(self, midplane):
|
def midplane(self, midplane):
|
||||||
"""
|
"""
|
||||||
Set the midplane model.
|
Sets the midplane model.
|
||||||
|
|
||||||
:returns: midplane model string (e.g. "vxr" or "std")
|
:returns: midplane model string (e.g. "vxr" or "std")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("c7200 set_midplane {name} {midplane}".format(name=self._name,
|
self._hypervisor.send("c7200 set_midplane {name} {midplane}".format(name=self._name,
|
||||||
midplane=midplane))
|
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
|
self._midplane = midplane
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -141,7 +174,7 @@ class C7200(Router):
|
|||||||
@sensors.setter
|
@sensors.setter
|
||||||
def sensors(self, sensors):
|
def sensors(self, sensors):
|
||||||
"""
|
"""
|
||||||
Set the 4 sensors with temperature in degree Celcius.
|
Sets the 4 sensors with temperature in degree Celcius.
|
||||||
|
|
||||||
:param sensors: list of 4 sensor temperatures corresponding to
|
:param sensors: list of 4 sensor temperatures corresponding to
|
||||||
sensor 1 = I/0 controller inlet
|
sensor 1 = I/0 controller inlet
|
||||||
@ -156,6 +189,13 @@ class C7200(Router):
|
|||||||
self._hypervisor.send("c7200 set_temp_sensor {name} {sensor_id} {temp}".format(name=self._name,
|
self._hypervisor.send("c7200 set_temp_sensor {name} {sensor_id} {temp}".format(name=self._name,
|
||||||
sensor_id=sensor_id,
|
sensor_id=sensor_id,
|
||||||
temp=sensor))
|
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
|
sensor_id += 1
|
||||||
self._sensors = sensors
|
self._sensors = sensors
|
||||||
|
|
||||||
@ -172,7 +212,7 @@ class C7200(Router):
|
|||||||
@power_supplies.setter
|
@power_supplies.setter
|
||||||
def power_supplies(self, power_supplies):
|
def power_supplies(self, power_supplies):
|
||||||
"""
|
"""
|
||||||
Set the 2 power supplies with 0 = off, 1 = on.
|
Sets the 2 power supplies with 0 = off, 1 = on.
|
||||||
|
|
||||||
:param power_supplies: list of 2 power supplies.
|
:param power_supplies: list of 2 power supplies.
|
||||||
Example: [1, 0] = first power supply is on, second is off.
|
Example: [1, 0] = first power supply is on, second is off.
|
||||||
@ -183,5 +223,11 @@ class C7200(Router):
|
|||||||
self._hypervisor.send("c7200 set_power_supply {name} {power_supply_id} {powered_on}".format(name=self._name,
|
self._hypervisor.send("c7200 set_power_supply {name} {power_supply_id} {powered_on}".format(name=self._name,
|
||||||
power_supply_id=power_supply_id,
|
power_supply_id=power_supply_id,
|
||||||
powered_on=power_supply))
|
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
|
power_supply_id += 1
|
||||||
|
|
||||||
self._power_supplies = power_supplies
|
self._power_supplies = power_supplies
|
||||||
|
@ -24,6 +24,9 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EthernetSwitch(object):
|
class EthernetSwitch(object):
|
||||||
"""
|
"""
|
||||||
@ -33,15 +36,47 @@ class EthernetSwitch(object):
|
|||||||
:param name: name for this switch
|
:param name: name for this switch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
_instance_count = 1
|
||||||
|
|
||||||
|
def __init__(self, hypervisor, name=None):
|
||||||
|
|
||||||
|
# create an unique ID
|
||||||
|
self._id = EthernetSwitch._instance_count
|
||||||
|
EthernetSwitch._instance_count += 1
|
||||||
|
|
||||||
|
# let's create a unique name if none has been chosen
|
||||||
|
if not name:
|
||||||
|
name = "SW" + str(self._id)
|
||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
||||||
self._hypervisor.send("ethsw create {}".format(self._name))
|
self._hypervisor.send("ethsw create {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}] has been created".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
self._hypervisor.devices.append(self)
|
self._hypervisor.devices.append(self)
|
||||||
self._nios = {}
|
self._nios = {}
|
||||||
self._mapping = {}
|
self._mapping = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
Returns the unique ID for this Ethernet switch.
|
||||||
|
|
||||||
|
:returns: id (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""
|
"""
|
||||||
@ -101,6 +136,11 @@ class EthernetSwitch(object):
|
|||||||
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
||||||
self._hypervisor.send("ethsw rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("ethsw rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_name))
|
new_name=new_name))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
new_name=new_name))
|
||||||
|
|
||||||
self._name = new_name
|
self._name = new_name
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
@ -109,6 +149,9 @@ class EthernetSwitch(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("ethsw delete {}".format(self._name))
|
self._hypervisor.send("ethsw delete {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}] has been deleted".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
self._hypervisor.devices.remove(self)
|
self._hypervisor.devices.remove(self)
|
||||||
|
|
||||||
def add_nio(self, nio, port):
|
def add_nio(self, nio, port):
|
||||||
@ -124,6 +167,11 @@ class EthernetSwitch(object):
|
|||||||
|
|
||||||
self._hypervisor.send("ethsw add_nio {name} {nio}".format(name=self._name,
|
self._hypervisor.send("ethsw add_nio {name} {nio}".format(name=self._name,
|
||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
self._nios[port] = nio
|
self._nios[port] = nio
|
||||||
|
|
||||||
def remove_nio(self, port):
|
def remove_nio(self, port):
|
||||||
@ -131,6 +179,8 @@ class EthernetSwitch(object):
|
|||||||
Removes the specified NIO as member of this Ethernet switch.
|
Removes the specified NIO as member of this Ethernet switch.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
|
|
||||||
|
:returns: the NIO that was bound to the port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if port not in self._nios:
|
if port not in self._nios:
|
||||||
@ -139,14 +189,22 @@ class EthernetSwitch(object):
|
|||||||
nio = self._nios[port]
|
nio = self._nios[port]
|
||||||
self._hypervisor.send("ethsw remove_nio {name} {nio}".format(name=self._name,
|
self._hypervisor.send("ethsw remove_nio {name} {nio}".format(name=self._name,
|
||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
del self._nios[port]
|
del self._nios[port]
|
||||||
|
|
||||||
if port in self._mapping:
|
if port in self._mapping:
|
||||||
del self._mapping[port]
|
del self._mapping[port]
|
||||||
|
|
||||||
|
return nio
|
||||||
|
|
||||||
def set_access_port(self, port, vlan_id):
|
def set_access_port(self, port, vlan_id):
|
||||||
"""
|
"""
|
||||||
Set the specified port as an ACCESS port.
|
Sets the specified port as an ACCESS port.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
:param vlan_id: VLAN number membership
|
:param vlan_id: VLAN number membership
|
||||||
@ -159,11 +217,16 @@ class EthernetSwitch(object):
|
|||||||
self._hypervisor.send("ethsw set_access_port {name} {nio} {vlan_id}".format(name=self._name,
|
self._hypervisor.send("ethsw set_access_port {name} {nio} {vlan_id}".format(name=self._name,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
vlan_id=vlan_id))
|
vlan_id=vlan_id))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: port {port} set as an access port in VLAN {vlan_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port,
|
||||||
|
vlan_id=vlan_id))
|
||||||
self._mapping[port] = ("access", vlan_id)
|
self._mapping[port] = ("access", vlan_id)
|
||||||
|
|
||||||
def set_dot1q_port(self, port, native_vlan):
|
def set_dot1q_port(self, port, native_vlan):
|
||||||
"""
|
"""
|
||||||
Set the specified port as a 802.1Q trunk port.
|
Sets the specified port as a 802.1Q trunk port.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
:param native_vlan: native VLAN for this trunk port
|
:param native_vlan: native VLAN for this trunk port
|
||||||
@ -176,11 +239,17 @@ class EthernetSwitch(object):
|
|||||||
self._hypervisor.send("ethsw set_dot1q_port {name} {nio} {native_vlan}".format(name=self._name,
|
self._hypervisor.send("ethsw set_dot1q_port {name} {nio} {native_vlan}".format(name=self._name,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
native_vlan=native_vlan))
|
native_vlan=native_vlan))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: port {port} set as a 802.1Q port with native VLAN {vlan_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port,
|
||||||
|
vlan_id=native_vlan))
|
||||||
|
|
||||||
self._mapping[port] = ("dot1q", native_vlan)
|
self._mapping[port] = ("dot1q", native_vlan)
|
||||||
|
|
||||||
def set_qinq_port(self, port, outer_vlan):
|
def set_qinq_port(self, port, outer_vlan):
|
||||||
"""
|
"""
|
||||||
Set the specified port as a trunk (QinQ) port.
|
Sets the specified port as a trunk (QinQ) port.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
:param outer_vlan: outer VLAN (transport VLAN) for this QinQ port
|
:param outer_vlan: outer VLAN (transport VLAN) for this QinQ port
|
||||||
@ -193,6 +262,11 @@ class EthernetSwitch(object):
|
|||||||
self._hypervisor.send("ethsw set_qinq_port {name} {nio} {outer_vlan}".format(name=self._name,
|
self._hypervisor.send("ethsw set_qinq_port {name} {nio} {outer_vlan}".format(name=self._name,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
outer_vlan=outer_vlan))
|
outer_vlan=outer_vlan))
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: port {port} set as a QinQ port with outer VLAN {vlan_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port=port,
|
||||||
|
vlan_id=outer_vlan))
|
||||||
self._mapping[port] = ("qinq", outer_vlan)
|
self._mapping[port] = ("qinq", outer_vlan)
|
||||||
|
|
||||||
def get_mac_addr_table(self):
|
def get_mac_addr_table(self):
|
||||||
|
@ -23,6 +23,9 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class FrameRelaySwitch(object):
|
class FrameRelaySwitch(object):
|
||||||
"""
|
"""
|
||||||
@ -32,15 +35,47 @@ class FrameRelaySwitch(object):
|
|||||||
:param name: name for this switch
|
:param name: name for this switch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
_instance_count = 1
|
||||||
|
|
||||||
|
def __init__(self, hypervisor, name=None):
|
||||||
|
|
||||||
|
# create an unique ID
|
||||||
|
self._id = FrameRelaySwitch._instance_count
|
||||||
|
FrameRelaySwitch._instance_count += 1
|
||||||
|
|
||||||
|
# let's create a unique name if none has been chosen
|
||||||
|
if not name:
|
||||||
|
name = "FR" + str(self._id)
|
||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
||||||
self._hypervisor.send("frsw create {}".format(self._name))
|
self._hypervisor.send("frsw create {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}] has been created".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
self._hypervisor.devices.append(self)
|
self._hypervisor.devices.append(self)
|
||||||
self._nios = {}
|
self._nios = {}
|
||||||
self._mapping = {}
|
self._mapping = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
Returns the unique ID for this Frame Relay switch.
|
||||||
|
|
||||||
|
:returns: id (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""
|
"""
|
||||||
@ -100,6 +135,11 @@ class FrameRelaySwitch(object):
|
|||||||
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
||||||
self._hypervisor.send("frsw rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("frsw rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_name))
|
new_name=new_name))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
new_name=new_name))
|
||||||
|
|
||||||
self._name = new_name
|
self._name = new_name
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
@ -108,8 +148,22 @@ class FrameRelaySwitch(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("frsw delete {}".format(self._name))
|
self._hypervisor.send("frsw delete {}".format(self._name))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}] has been deleted".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
self._hypervisor.devices.remove(self)
|
self._hypervisor.devices.remove(self)
|
||||||
|
|
||||||
|
def has_port(self, port):
|
||||||
|
"""
|
||||||
|
Checks if a port exists on this Frame Relay switch.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if port in self._nios:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def add_nio(self, nio, port):
|
def add_nio(self, nio, port):
|
||||||
"""
|
"""
|
||||||
Adds a NIO as new port on Frame Relay switch.
|
Adds a NIO as new port on Frame Relay switch.
|
||||||
@ -121,6 +175,11 @@ class FrameRelaySwitch(object):
|
|||||||
if port in self._nios:
|
if port in self._nios:
|
||||||
raise DynamipsError("Port {} isn't free".format(port))
|
raise DynamipsError("Port {} isn't free".format(port))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
self._nios[port] = nio
|
self._nios[port] = nio
|
||||||
|
|
||||||
def remove_nio(self, port):
|
def remove_nio(self, port):
|
||||||
@ -128,12 +187,21 @@ class FrameRelaySwitch(object):
|
|||||||
Removes the specified NIO as member of this Frame Relay switch.
|
Removes the specified NIO as member of this Frame Relay switch.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
|
|
||||||
|
:returns: the NIO that was bound to the allocated port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if port not in self._nios:
|
if port not in self._nios:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port))
|
raise DynamipsError("Port {} is not allocated".format(port))
|
||||||
|
|
||||||
|
nio = self._nios[port]
|
||||||
|
log.info("Frame Relay switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
del self._nios[port]
|
del self._nios[port]
|
||||||
|
return nio
|
||||||
|
|
||||||
def map_vc(self, port1, dlci1, port2, dlci2):
|
def map_vc(self, port1, dlci1, port2, dlci2):
|
||||||
"""
|
"""
|
||||||
@ -159,6 +227,14 @@ class FrameRelaySwitch(object):
|
|||||||
input_dlci=dlci1,
|
input_dlci=dlci1,
|
||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_dlci=dlci2))
|
output_dlci=dlci2))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}]: VC from port {port1} DLCI {dlci1} to port {port2} DLCI {dlci2} created".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
dlci1=dlci1,
|
||||||
|
port2=port2,
|
||||||
|
dlci2=dlci2))
|
||||||
|
|
||||||
self._mapping[(port1, dlci1)] = (port2, dlci2)
|
self._mapping[(port1, dlci1)] = (port2, dlci2)
|
||||||
|
|
||||||
def unmap_vc(self, port1, dlci1, port2, dlci2):
|
def unmap_vc(self, port1, dlci1, port2, dlci2):
|
||||||
@ -185,4 +261,11 @@ class FrameRelaySwitch(object):
|
|||||||
input_dlci=dlci1,
|
input_dlci=dlci1,
|
||||||
output_nio=nio2,
|
output_nio=nio2,
|
||||||
output_dlci=dlci2))
|
output_dlci=dlci2))
|
||||||
|
|
||||||
|
log.info("Frame Relay switch {name} [id={id}]: VC from port {port1} DLCI {dlci1} to port {port2} DLCI {dlci2} deleted".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
port1=port1,
|
||||||
|
dlci1=dlci1,
|
||||||
|
port2=port2,
|
||||||
|
dlci2=dlci2))
|
||||||
del self._mapping[(port1, dlci1)]
|
del self._mapping[(port1, dlci1)]
|
||||||
|
@ -23,6 +23,9 @@ from __future__ import unicode_literals
|
|||||||
from .bridge import Bridge
|
from .bridge import Bridge
|
||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Hub(Bridge):
|
class Hub(Bridge):
|
||||||
"""
|
"""
|
||||||
@ -32,10 +35,41 @@ class Hub(Bridge):
|
|||||||
:param name: name for this hub
|
:param name: name for this hub
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_instance_count = 1
|
||||||
|
|
||||||
def __init__(self, hypervisor, name):
|
def __init__(self, hypervisor, name):
|
||||||
|
|
||||||
Bridge.__init__(self, hypervisor, name)
|
# create an unique ID
|
||||||
|
self._id = Hub._instance_count
|
||||||
|
Hub._instance_count += 1
|
||||||
|
|
||||||
|
# let's create a unique name if none has been chosen
|
||||||
|
if not name:
|
||||||
|
name = "Hub" + str(self._id)
|
||||||
|
|
||||||
self._mapping = {}
|
self._mapping = {}
|
||||||
|
Bridge.__init__(self, hypervisor, name)
|
||||||
|
|
||||||
|
log.info("Ethernet hub {name} [id={id}] has been created".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
Returns the unique ID for this Ethernet switch.
|
||||||
|
|
||||||
|
:returns: id (integer)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mapping(self):
|
def mapping(self):
|
||||||
@ -47,6 +81,15 @@ class Hub(Bridge):
|
|||||||
|
|
||||||
return self._mapping
|
return self._mapping
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""
|
||||||
|
Deletes this hub.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Bridge.delete(self)
|
||||||
|
log.info("Ethernet hub {name} [id={id}] has been deleted".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
def add_nio(self, nio, port):
|
def add_nio(self, nio, port):
|
||||||
"""
|
"""
|
||||||
Adds a NIO as new port on this hub.
|
Adds a NIO as new port on this hub.
|
||||||
@ -59,6 +102,11 @@ class Hub(Bridge):
|
|||||||
raise DynamipsError("Port {} isn't free".format(port))
|
raise DynamipsError("Port {} isn't free".format(port))
|
||||||
|
|
||||||
Bridge.add_nio(self, nio)
|
Bridge.add_nio(self, nio)
|
||||||
|
|
||||||
|
log.info("Ethernet hub {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
self._mapping[port] = nio
|
self._mapping[port] = nio
|
||||||
|
|
||||||
def remove_nio(self, port):
|
def remove_nio(self, port):
|
||||||
@ -66,6 +114,8 @@ class Hub(Bridge):
|
|||||||
Removes the specified NIO as member of this hub.
|
Removes the specified NIO as member of this hub.
|
||||||
|
|
||||||
:param port: allocated port
|
:param port: allocated port
|
||||||
|
|
||||||
|
:returns: the NIO that was bound to the allocated port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if port not in self._mapping:
|
if port not in self._mapping:
|
||||||
@ -73,4 +123,11 @@ class Hub(Bridge):
|
|||||||
|
|
||||||
nio = self._mapping[port]
|
nio = self._mapping[port]
|
||||||
Bridge.remove_nio(self, nio)
|
Bridge.remove_nio(self, nio)
|
||||||
|
|
||||||
|
log.info("Ethernet switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio=nio,
|
||||||
|
port=port))
|
||||||
|
|
||||||
del self._mapping[port]
|
del self._mapping[port]
|
||||||
|
return nio
|
||||||
|
@ -24,29 +24,36 @@ from __future__ import unicode_literals
|
|||||||
from ..dynamips_error import DynamipsError
|
from ..dynamips_error import DynamipsError
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Router(object):
|
class Router(object):
|
||||||
"""
|
"""
|
||||||
Dynamips router
|
Dynamips router implementation.
|
||||||
|
|
||||||
:param hypervisor: Dynamips hypervisor object
|
:param hypervisor: Dynamips hypervisor object
|
||||||
:param name: name for this router
|
:param name: name for this router
|
||||||
:param platform: c7200, c3745, c3725, c3600, c2691, c2600 or c1700
|
:param platform: c7200, c3745, c3725, c3600, c2691, c2600 or c1700
|
||||||
:param console_flag: create console ports if True.
|
:param ghost_flag: used when creating a ghost IOS.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_instance_count = 0
|
_instance_count = 1
|
||||||
_status = {0: "inactive",
|
_status = {0: "inactive",
|
||||||
1: "shutting down",
|
1: "shutting down",
|
||||||
2: "running",
|
2: "running",
|
||||||
3: "suspended"}
|
3: "suspended"}
|
||||||
|
|
||||||
def __init__(self, hypervisor, name, platform="c7200", console_flag=True):
|
def __init__(self, hypervisor, name=None, platform="c7200", ghost_flag=False):
|
||||||
|
|
||||||
# create an unique ID
|
# create an unique ID
|
||||||
self._id = Router._instance_count
|
self._id = Router._instance_count
|
||||||
Router._instance_count += 1
|
Router._instance_count += 1
|
||||||
|
|
||||||
|
# let's create a unique name if none has been chosen
|
||||||
|
if not name:
|
||||||
|
name = "R" + str(self._id)
|
||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
self._name = '"' + name + '"' # put name into quotes to protect spaces
|
||||||
self._platform = platform
|
self._platform = platform
|
||||||
@ -76,12 +83,66 @@ class Router(object):
|
|||||||
id=self._id,
|
id=self._id,
|
||||||
platform=self._platform))
|
platform=self._platform))
|
||||||
|
|
||||||
if console_flag:
|
if not ghost_flag:
|
||||||
|
log.info("router {platform} {name} [id={id}] has been created".format(name=self._name,
|
||||||
|
platform=platform,
|
||||||
|
id=self._id))
|
||||||
self.console = self._hypervisor.baseconsole + self._id
|
self.console = self._hypervisor.baseconsole + self._id
|
||||||
self.aux = self._hypervisor.baseaux + self._id
|
self.aux = self._hypervisor.baseaux + self._id
|
||||||
|
else:
|
||||||
|
log.info("creating a new ghost IOS file")
|
||||||
|
Router._instance_count -= 1
|
||||||
|
|
||||||
self._hypervisor.devices.append(self)
|
self._hypervisor.devices.append(self)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
"""
|
||||||
|
Reset the instance count.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls._instance_count = 1
|
||||||
|
|
||||||
|
def defaults(self):
|
||||||
|
"""
|
||||||
|
Returns all the default base attribute values for routers.
|
||||||
|
|
||||||
|
:returns: default values (dictionary)
|
||||||
|
"""
|
||||||
|
|
||||||
|
router_defaults = {"platform": self._platform,
|
||||||
|
"image": self._image,
|
||||||
|
"ram": self._ram,
|
||||||
|
"nvram": self._nvram,
|
||||||
|
"mmap": self._mmap,
|
||||||
|
"sparsemem": self._sparsemem,
|
||||||
|
"clock_divisor": self._clock_divisor,
|
||||||
|
"idlepc": self._idlepc,
|
||||||
|
"idlemax": self._idlemax,
|
||||||
|
"idlesleep": self._idlesleep,
|
||||||
|
"exec_area": self._exec_area,
|
||||||
|
"jit_sharing_group": self._jit_sharing_group,
|
||||||
|
"disk0": self._disk0,
|
||||||
|
"disk1": self._disk1,
|
||||||
|
"confreg": self._confreg,
|
||||||
|
"console": self._console,
|
||||||
|
"aux": self._aux,
|
||||||
|
"mac_addr": self._mac_addr,
|
||||||
|
"system_id": self._system_id}
|
||||||
|
|
||||||
|
slot_id = 0
|
||||||
|
for slot in self._slots:
|
||||||
|
if slot:
|
||||||
|
slot = str(slot)
|
||||||
|
router_defaults["slot" + str(slot_id)] = slot
|
||||||
|
slot_id += 1
|
||||||
|
|
||||||
|
if self._slots[0] and self._slots[0].wics:
|
||||||
|
for wic_slot_id in range(0, len(self._slots[0].wics)):
|
||||||
|
router_defaults["wic" + str(wic_slot_id)] = None
|
||||||
|
|
||||||
|
return router_defaults
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
"""
|
"""
|
||||||
@ -151,6 +212,11 @@ class Router(object):
|
|||||||
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
|
||||||
self._hypervisor.send("vm rename {name} {new_name}".format(name=self._name,
|
self._hypervisor.send("vm rename {name} {new_name}".format(name=self._name,
|
||||||
new_name=new_name))
|
new_name=new_name))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: renamed to {new_name}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
new_name=new_name))
|
||||||
|
|
||||||
self._name = new_name
|
self._name = new_name
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
@ -161,13 +227,19 @@ class Router(object):
|
|||||||
self._hypervisor.send("vm delete {}".format(self._name))
|
self._hypervisor.send("vm delete {}".format(self._name))
|
||||||
self._hypervisor.devices.remove(self)
|
self._hypervisor.devices.remove(self)
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}] has been deleted".format(name=self._name, id=self._id))
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""
|
"""
|
||||||
Starts this router.
|
Starts this router.
|
||||||
At least the IOS image must be set.
|
At least the IOS image must be set before starting it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm start {}".format(self._name))
|
if self.get_status() == "suspended":
|
||||||
|
self.resume()
|
||||||
|
else:
|
||||||
|
self._hypervisor.send("vm start {}".format(self._name))
|
||||||
|
log.info("router {name} [id={id}] has been started".format(name=self._name, id=self._id))
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
@ -176,13 +248,16 @@ class Router(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm stop {}".format(self._name))
|
self._hypervisor.send("vm stop {}".format(self._name))
|
||||||
|
log.info("router {name} [id={id}] has been stopped".format(name=self._name, id=self._id))
|
||||||
|
|
||||||
def suspend(self):
|
def suspend(self):
|
||||||
"""
|
"""
|
||||||
Suspends this router
|
Suspends this router
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm suspend {}".format(self._name))
|
if self.get_status() == "running":
|
||||||
|
self._hypervisor.send("vm suspend {}".format(self._name))
|
||||||
|
log.info("router {name} [id={id}] has been suspended".format(name=self._name, id=self._id))
|
||||||
|
|
||||||
def resume(self):
|
def resume(self):
|
||||||
"""
|
"""
|
||||||
@ -190,12 +265,13 @@ class Router(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm resume {}".format(self._name))
|
self._hypervisor.send("vm resume {}".format(self._name))
|
||||||
|
log.info("router {name} [id={id}] has been resumed".format(name=self._name, id=self._id))
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
"""
|
"""
|
||||||
Returns the status of this router
|
Returns the status of this router
|
||||||
|
|
||||||
:returns: 0=inactive, 1=shutting down, 2=running, 3=suspended
|
:returns: inactive, shutting down, running or suspended.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
status_id = int(self._hypervisor.send("vm get_status {}".format(self._name))[0])
|
status_id = int(self._hypervisor.send("vm get_status {}".format(self._name))[0])
|
||||||
@ -225,7 +301,7 @@ class Router(object):
|
|||||||
@jit_sharing_group.setter
|
@jit_sharing_group.setter
|
||||||
def jit_sharing_group(self, group_id):
|
def jit_sharing_group(self, group_id):
|
||||||
"""
|
"""
|
||||||
Set the translation sharing group (unstable).
|
Sets the translation sharing group (unstable).
|
||||||
|
|
||||||
:param group_id: translation sharing group ID
|
:param group_id: translation sharing group ID
|
||||||
"""
|
"""
|
||||||
@ -236,12 +312,16 @@ class Router(object):
|
|||||||
self._hypervisor.send("vm set_tsg {name} {group_id}".format(name=self._name,
|
self._hypervisor.send("vm set_tsg {name} {group_id}".format(name=self._name,
|
||||||
group_id=group_id))
|
group_id=group_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: set in JIT sharing group {group_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
group_id=group_id))
|
||||||
|
|
||||||
self._jit_sharing_group = group_id
|
self._jit_sharing_group = group_id
|
||||||
self._hypervisor.add_jitsharing_group(os.path.basename(self._image), group_id)
|
self._hypervisor.add_jitsharing_group(os.path.basename(self._image), group_id)
|
||||||
|
|
||||||
def set_debug_level(self, level):
|
def set_debug_level(self, level):
|
||||||
"""
|
"""
|
||||||
Set the debug level for this router (default is 0).
|
Sets the debug level for this router (default is 0).
|
||||||
|
|
||||||
:param level: level number
|
:param level: level number
|
||||||
"""
|
"""
|
||||||
@ -262,7 +342,7 @@ class Router(object):
|
|||||||
@image.setter
|
@image.setter
|
||||||
def image(self, image):
|
def image(self, image):
|
||||||
"""
|
"""
|
||||||
Set the IOS image for this router.
|
Sets the IOS image for this router.
|
||||||
There is no default.
|
There is no default.
|
||||||
|
|
||||||
:param image: path to IOS image file
|
:param image: path to IOS image file
|
||||||
@ -271,11 +351,16 @@ class Router(object):
|
|||||||
# encase image in quotes to protect spaces in the path
|
# encase image in quotes to protect spaces in the path
|
||||||
self._hypervisor.send("vm set_ios {name} {image}".format(name=self._name,
|
self._hypervisor.send("vm set_ios {name} {image}".format(name=self._name,
|
||||||
image='"' + image + '"'))
|
image='"' + image + '"'))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: has a new IOS image set: {image}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
image='"' + image + '"'))
|
||||||
|
|
||||||
self._image = image
|
self._image = image
|
||||||
|
|
||||||
def set_config(self, startup_config, private_config=''):
|
def set_config(self, startup_config, private_config=''):
|
||||||
"""
|
"""
|
||||||
Set the config files that are pushed to startup-config and
|
Sets the config files that are pushed to startup-config and
|
||||||
private-config in NVRAM when the instance is started.
|
private-config in NVRAM when the instance is started.
|
||||||
|
|
||||||
:param startup_config: path to statup-config file
|
:param startup_config: path to statup-config file
|
||||||
@ -287,6 +372,15 @@ class Router(object):
|
|||||||
startup='"' + startup_config + '"',
|
startup='"' + startup_config + '"',
|
||||||
private='"' + private_config + '"'))
|
private='"' + private_config + '"'))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: has a startup-config set: {startup}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
startup='"' + startup_config + '"'))
|
||||||
|
|
||||||
|
if private_config:
|
||||||
|
log.info("router {name} [id={id}]: has a private-config set: {private}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
private='"' + private_config + '"'))
|
||||||
|
|
||||||
def extract_config(self):
|
def extract_config(self):
|
||||||
"""
|
"""
|
||||||
Gets the contents of the config files
|
Gets the contents of the config files
|
||||||
@ -318,6 +412,13 @@ class Router(object):
|
|||||||
startup=startup_config,
|
startup=startup_config,
|
||||||
private=private_config))
|
private=private_config))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: new startup-config pushed".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
|
if private_config != '(keep)':
|
||||||
|
log.info("router {name} [id={id}]: new private-config pushed".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ram(self):
|
def ram(self):
|
||||||
"""
|
"""
|
||||||
@ -331,13 +432,22 @@ class Router(object):
|
|||||||
@ram.setter
|
@ram.setter
|
||||||
def ram(self, ram):
|
def ram(self, ram):
|
||||||
"""
|
"""
|
||||||
Set amount of RAM allocated to this router
|
Sets amount of RAM allocated to this router
|
||||||
|
|
||||||
:param ram: amount of RAM in Mbytes (integer)
|
:param ram: amount of RAM in Mbytes (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self._ram == ram:
|
||||||
|
return
|
||||||
|
|
||||||
self._hypervisor.send("vm set_ram {name} {ram}".format(name=self._name,
|
self._hypervisor.send("vm set_ram {name} {ram}".format(name=self._name,
|
||||||
ram=self._ram))
|
ram=ram))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: RAM updated from {old_ram}MB to {new_ram}MB".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_ram=self._ram,
|
||||||
|
new_ram=ram))
|
||||||
|
|
||||||
self._hypervisor.decrease_memory_load(self._ram)
|
self._hypervisor.decrease_memory_load(self._ram)
|
||||||
self._ram = ram
|
self._ram = ram
|
||||||
self._hypervisor.increase_memory_load(self._ram)
|
self._hypervisor.increase_memory_load(self._ram)
|
||||||
@ -355,13 +465,21 @@ class Router(object):
|
|||||||
@nvram.setter
|
@nvram.setter
|
||||||
def nvram(self, nvram):
|
def nvram(self, nvram):
|
||||||
"""
|
"""
|
||||||
Set amount of NVRAM allocated to this router
|
Sets amount of NVRAM allocated to this router
|
||||||
|
|
||||||
:param nvram: amount of NVRAM in Kbytes (integer)
|
:param nvram: amount of NVRAM in Kbytes (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self._nvram == nvram:
|
||||||
|
return
|
||||||
|
|
||||||
self._hypervisor.send("vm set_nvram {name} {nvram}".format(name=self._name,
|
self._hypervisor.send("vm set_nvram {name} {nvram}".format(name=self._name,
|
||||||
nvram=self._nvram))
|
nvram=nvram))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_nvram=self._nvram,
|
||||||
|
new_nvram=nvram))
|
||||||
self._nvram = nvram
|
self._nvram = nvram
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -389,6 +507,13 @@ class Router(object):
|
|||||||
flag = 0
|
flag = 0
|
||||||
self._hypervisor.send("vm set_ram_mmap {name} {mmap}".format(name=self._name,
|
self._hypervisor.send("vm set_ram_mmap {name} {mmap}".format(name=self._name,
|
||||||
mmap=flag))
|
mmap=flag))
|
||||||
|
|
||||||
|
if mmap:
|
||||||
|
log.info("router {name} [id={id}]: mmap enabled".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
else:
|
||||||
|
log.info("router {name} [id={id}]: mmap disabled".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
self._mmap = mmap
|
self._mmap = mmap
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -415,6 +540,13 @@ class Router(object):
|
|||||||
flag = 0
|
flag = 0
|
||||||
self._hypervisor.send("vm set_sparse_mem {name} {sparsemem}".format(name=self._name,
|
self._hypervisor.send("vm set_sparse_mem {name} {sparsemem}".format(name=self._name,
|
||||||
sparsemem=flag))
|
sparsemem=flag))
|
||||||
|
|
||||||
|
if sparsemem:
|
||||||
|
log.info("router {name} [id={id}]: sparse memory enabled".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
|
else:
|
||||||
|
log.info("router {name} [id={id}]: sparse memory disabled".format(name=self._name,
|
||||||
|
id=self._id))
|
||||||
self._sparsemem = sparsemem
|
self._sparsemem = sparsemem
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -430,7 +562,7 @@ class Router(object):
|
|||||||
@clock_divisor.setter
|
@clock_divisor.setter
|
||||||
def clock_divisor(self, clock_divisor):
|
def clock_divisor(self, clock_divisor):
|
||||||
"""
|
"""
|
||||||
Set the clock divisor value. The higher is the value, the faster is the clock in the
|
Sets the clock divisor value. The higher is the value, the faster is the clock in the
|
||||||
virtual machine. The default is 4, but it is often required to adjust it.
|
virtual machine. The default is 4, but it is often required to adjust it.
|
||||||
|
|
||||||
:param clock_divisor: clock divisor value (integer)
|
:param clock_divisor: clock divisor value (integer)
|
||||||
@ -438,6 +570,11 @@ class Router(object):
|
|||||||
|
|
||||||
self._hypervisor.send("vm set_clock_divisor {name} {clock}".format(name=self._name,
|
self._hypervisor.send("vm set_clock_divisor {name} {clock}".format(name=self._name,
|
||||||
clock=clock_divisor))
|
clock=clock_divisor))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: clock divisor updated from {old_clock} to {new_clock}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_clock=self._clock_divisor,
|
||||||
|
new_clock=clock_divisor))
|
||||||
self._clock_divisor = clock_divisor
|
self._clock_divisor = clock_divisor
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -453,7 +590,7 @@ class Router(object):
|
|||||||
@idlepc.setter
|
@idlepc.setter
|
||||||
def idlepc(self, idlepc):
|
def idlepc(self, idlepc):
|
||||||
"""
|
"""
|
||||||
Set the idle Pointer Counter (PC)
|
Sets the idle Pointer Counter (PC)
|
||||||
|
|
||||||
:param idlepc: idlepc value (string)
|
:param idlepc: idlepc value (string)
|
||||||
"""
|
"""
|
||||||
@ -465,6 +602,11 @@ class Router(object):
|
|||||||
else:
|
else:
|
||||||
self._hypervisor.send("vm set_idle_pc_online {name} 0 {idlepc}".format(name=self._name,
|
self._hypervisor.send("vm set_idle_pc_online {name} 0 {idlepc}".format(name=self._name,
|
||||||
idlepc=idlepc))
|
idlepc=idlepc))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: idle-PC set to {idlepc}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
idlepc=idlepc))
|
||||||
|
|
||||||
self._idlepc = idlepc
|
self._idlepc = idlepc
|
||||||
|
|
||||||
def get_idle_pc_prop(self):
|
def get_idle_pc_prop(self):
|
||||||
@ -500,7 +642,7 @@ class Router(object):
|
|||||||
@idlemax.setter
|
@idlemax.setter
|
||||||
def idlemax(self, idlemax):
|
def idlemax(self, idlemax):
|
||||||
"""
|
"""
|
||||||
Set CPU idle max value
|
Sets CPU idle max value
|
||||||
|
|
||||||
:param idlemax: idle max value (integer)
|
:param idlemax: idle max value (integer)
|
||||||
"""
|
"""
|
||||||
@ -508,6 +650,12 @@ class Router(object):
|
|||||||
if self.is_running(): # router is running
|
if self.is_running(): # router is running
|
||||||
self._hypervisor.send("vm set_idle_max {name} 0 {idlemax}".format(name=self._name,
|
self._hypervisor.send("vm set_idle_max {name} 0 {idlemax}".format(name=self._name,
|
||||||
idlemax=idlemax))
|
idlemax=idlemax))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: idlemax updated from {old_idlemax} to {new_idlemax}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_idlemax=self._idlemax,
|
||||||
|
new_idlemax=idlemax))
|
||||||
|
|
||||||
self._idlemax = idlemax
|
self._idlemax = idlemax
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -523,7 +671,7 @@ class Router(object):
|
|||||||
@idlesleep.setter
|
@idlesleep.setter
|
||||||
def idlesleep(self, idlesleep):
|
def idlesleep(self, idlesleep):
|
||||||
"""
|
"""
|
||||||
Set CPU idle sleep time value.
|
Sets CPU idle sleep time value.
|
||||||
|
|
||||||
:param idlesleep: idle sleep value (integer)
|
:param idlesleep: idle sleep value (integer)
|
||||||
"""
|
"""
|
||||||
@ -531,6 +679,12 @@ class Router(object):
|
|||||||
if self.is_running(): # router is running
|
if self.is_running(): # router is running
|
||||||
self._hypervisor.send("vm set_idle_sleep_time {name} 0 {idlesleep}".format(name=self._name,
|
self._hypervisor.send("vm set_idle_sleep_time {name} 0 {idlesleep}".format(name=self._name,
|
||||||
idlesleep=idlesleep))
|
idlesleep=idlesleep))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: idlesleep updated from {old_idlesleep} to {new_idlesleep}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_idlesleep=self._idlesleep,
|
||||||
|
new_idlesleep=idlesleep))
|
||||||
|
|
||||||
self._idlesleep = idlesleep
|
self._idlesleep = idlesleep
|
||||||
|
|
||||||
def show_timer_drift(self):
|
def show_timer_drift(self):
|
||||||
@ -555,16 +709,21 @@ class Router(object):
|
|||||||
@ghost_file.setter
|
@ghost_file.setter
|
||||||
def ghost_file(self, ghost_file):
|
def ghost_file(self, ghost_file):
|
||||||
"""
|
"""
|
||||||
Set ghost RAM file
|
Sets ghost RAM file
|
||||||
|
|
||||||
:ghost_file: path to ghost file
|
:ghost_file: path to ghost file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm set_ghost_file {name} {ghost_file}".format(name=self._name,
|
self._hypervisor.send("vm set_ghost_file {name} {ghost_file}".format(name=self._name,
|
||||||
ghost_file=ghost_file))
|
ghost_file=ghost_file))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: ghost file set to {ghost_file}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
ghost_file=ghost_file))
|
||||||
|
|
||||||
self._ghost_file = ghost_file
|
self._ghost_file = ghost_file
|
||||||
|
|
||||||
# If this is a ghost instance, track this as a hosted ghost instance by this hypervisor
|
# if this is a ghost instance, track this as a hosted ghost instance by this hypervisor
|
||||||
if self.ghost_status == 1:
|
if self.ghost_status == 1:
|
||||||
self._hypervisor.add_ghost(ghost_file, self)
|
self._hypervisor.add_ghost(ghost_file, self)
|
||||||
|
|
||||||
@ -575,8 +734,8 @@ class Router(object):
|
|||||||
:returns: formatted ghost_file name (string)
|
:returns: formatted ghost_file name (string)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Replace specials characters in 'drive:\filename' in Linux and Dynamips in MS Windows or viceversa.
|
# replace specials characters in 'drive:\filename' in Linux and Dynamips in MS Windows or viceversa.
|
||||||
ghost_file = os.path.basename(self._image) + '-' + self._hypervisor.host + '.ghost'
|
ghost_file = "{}-{}.ghost".format(os.path.basename(self._image), self._ram)
|
||||||
ghost_file = ghost_file.replace('\\', '-').replace('/', '-').replace(':', '-')
|
ghost_file = ghost_file.replace('\\', '-').replace('/', '-').replace(':', '-')
|
||||||
return ghost_file
|
return ghost_file
|
||||||
|
|
||||||
@ -592,7 +751,7 @@ class Router(object):
|
|||||||
@ghost_status.setter
|
@ghost_status.setter
|
||||||
def ghost_status(self, ghost_status):
|
def ghost_status(self, ghost_status):
|
||||||
"""
|
"""
|
||||||
Set ghost RAM status
|
Sets ghost RAM status
|
||||||
|
|
||||||
:param ghost_status: state flag indicating status
|
:param ghost_status: state flag indicating status
|
||||||
0 => Do not use IOS ghosting
|
0 => Do not use IOS ghosting
|
||||||
@ -602,6 +761,10 @@ class Router(object):
|
|||||||
|
|
||||||
self._hypervisor.send("vm set_ghost_status {name} {ghost_status}".format(name=self._name,
|
self._hypervisor.send("vm set_ghost_status {name} {ghost_status}".format(name=self._name,
|
||||||
ghost_status=ghost_status))
|
ghost_status=ghost_status))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: ghost status set to {ghost_status}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
ghost_status=ghost_status))
|
||||||
self._ghost_status = ghost_status
|
self._ghost_status = ghost_status
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -617,7 +780,7 @@ class Router(object):
|
|||||||
@exec_area.setter
|
@exec_area.setter
|
||||||
def exec_area(self, exec_area):
|
def exec_area(self, exec_area):
|
||||||
"""
|
"""
|
||||||
Set the exec area value.
|
Sets the exec area value.
|
||||||
The exec area is a pool of host memory used to store pages
|
The exec area is a pool of host memory used to store pages
|
||||||
translated by the JIT (they contain the native code
|
translated by the JIT (they contain the native code
|
||||||
corresponding to MIPS code pages).
|
corresponding to MIPS code pages).
|
||||||
@ -627,6 +790,11 @@ class Router(object):
|
|||||||
|
|
||||||
self._hypervisor.send("vm set_exec_area {name} {exec_area}".format(name=self._name,
|
self._hypervisor.send("vm set_exec_area {name} {exec_area}".format(name=self._name,
|
||||||
exec_area=exec_area))
|
exec_area=exec_area))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: exec area updated from {old_exec}MB to {new_exec}MB".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_exec=self._exec_area,
|
||||||
|
new_exec=exec_area))
|
||||||
self._exec_area = exec_area
|
self._exec_area = exec_area
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -642,13 +810,18 @@ class Router(object):
|
|||||||
@disk0.setter
|
@disk0.setter
|
||||||
def disk0(self, disk0):
|
def disk0(self, disk0):
|
||||||
"""
|
"""
|
||||||
Set the size (MB) for PCMCIA disk0.
|
Sets the size (MB) for PCMCIA disk0.
|
||||||
|
|
||||||
:param disk0: disk0 size (integer)
|
:param disk0: disk0 size (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm set_disk0 {name} {disk0}".format(name=self._name,
|
self._hypervisor.send("vm set_disk0 {name} {disk0}".format(name=self._name,
|
||||||
disk0=disk0))
|
disk0=disk0))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: disk0 updated from {old_disk0}MB to {new_disk0}MB".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_disk0=self._disk0,
|
||||||
|
new_disk0=disk0))
|
||||||
self._disk0 = disk0
|
self._disk0 = disk0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -664,13 +837,18 @@ class Router(object):
|
|||||||
@disk1.setter
|
@disk1.setter
|
||||||
def disk1(self, disk1):
|
def disk1(self, disk1):
|
||||||
"""
|
"""
|
||||||
Set the size (MB) for PCMCIA disk1.
|
Sets the size (MB) for PCMCIA disk1.
|
||||||
|
|
||||||
:param disk1: disk1 size (integer)
|
:param disk1: disk1 size (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm set_disk1 {name} {disk1}".format(name=self._name,
|
self._hypervisor.send("vm set_disk1 {name} {disk1}".format(name=self._name,
|
||||||
disk1=disk1))
|
disk1=disk1))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: disk1 updated from {old_disk1}MB to {new_disk1}MB".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_disk1=self._disk1,
|
||||||
|
new_disk1=disk1))
|
||||||
self._disk1 = disk1
|
self._disk1 = disk1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -687,13 +865,18 @@ class Router(object):
|
|||||||
@confreg.setter
|
@confreg.setter
|
||||||
def confreg(self, confreg):
|
def confreg(self, confreg):
|
||||||
"""
|
"""
|
||||||
Set the configuration register.
|
Sets the configuration register.
|
||||||
|
|
||||||
:param confreg: configuration register value (string)
|
:param confreg: configuration register value (string)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._hypervisor.send("vm set_conf_reg {name} {confreg}".format(name=self._name,
|
self._hypervisor.send("vm set_conf_reg {name} {confreg}".format(name=self._name,
|
||||||
confreg=confreg))
|
confreg=confreg))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: confreg updated from {old_confreg} to {new_confreg}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_confreg=self._confreg,
|
||||||
|
new_confreg=confreg))
|
||||||
self._confreg = confreg
|
self._confreg = confreg
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -709,7 +892,7 @@ class Router(object):
|
|||||||
@console.setter
|
@console.setter
|
||||||
def console(self, console):
|
def console(self, console):
|
||||||
"""
|
"""
|
||||||
Set the TCP console port.
|
Sets the TCP console port.
|
||||||
|
|
||||||
:param console: console port (integer)
|
:param console: console port (integer)
|
||||||
"""
|
"""
|
||||||
@ -719,6 +902,11 @@ class Router(object):
|
|||||||
|
|
||||||
self._hypervisor.send("vm set_con_tcp_port {name} {console}".format(name=self._name,
|
self._hypervisor.send("vm set_con_tcp_port {name} {console}".format(name=self._name,
|
||||||
console=console))
|
console=console))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: console port updated from {old_console} to {new_console}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_console=self._console,
|
||||||
|
new_console=console))
|
||||||
self._console = console
|
self._console = console
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -734,7 +922,7 @@ class Router(object):
|
|||||||
@aux.setter
|
@aux.setter
|
||||||
def aux(self, aux):
|
def aux(self, aux):
|
||||||
"""
|
"""
|
||||||
Set the TCP auxiliary port.
|
Sets the TCP auxiliary port.
|
||||||
|
|
||||||
:param aux: console auxiliary port (integer)
|
:param aux: console auxiliary port (integer)
|
||||||
"""
|
"""
|
||||||
@ -744,6 +932,11 @@ class Router(object):
|
|||||||
|
|
||||||
self._hypervisor.send("vm set_aux_tcp_port {name} {aux}".format(name=self._name,
|
self._hypervisor.send("vm set_aux_tcp_port {name} {aux}".format(name=self._name,
|
||||||
aux=aux))
|
aux=aux))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: aux port updated from {old_aux} to {new_aux}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_aux=self._aux,
|
||||||
|
new_aux=aux))
|
||||||
self._aux = aux
|
self._aux = aux
|
||||||
|
|
||||||
def get_cpu_info(self, cpu_id=0):
|
def get_cpu_info(self, cpu_id=0):
|
||||||
@ -801,7 +994,7 @@ class Router(object):
|
|||||||
@mac_addr.setter
|
@mac_addr.setter
|
||||||
def mac_addr(self, mac_addr):
|
def mac_addr(self, mac_addr):
|
||||||
"""
|
"""
|
||||||
Set the MAC address.
|
Sets the MAC address.
|
||||||
|
|
||||||
:param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
|
:param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
|
||||||
"""
|
"""
|
||||||
@ -809,6 +1002,11 @@ class Router(object):
|
|||||||
self._hypervisor.send("{platform} set_mac_addr {name} {mac_addr}".format(platform=self._platform,
|
self._hypervisor.send("{platform} set_mac_addr {name} {mac_addr}".format(platform=self._platform,
|
||||||
name=self._name,
|
name=self._name,
|
||||||
mac_addr=mac_addr))
|
mac_addr=mac_addr))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: MAC address updated from {old_mac} to {new_mac}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_mac=self._mac_addr,
|
||||||
|
new_mac=mac_addr))
|
||||||
self._mac_addr = mac_addr
|
self._mac_addr = mac_addr
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -824,7 +1022,7 @@ class Router(object):
|
|||||||
@system_id.setter
|
@system_id.setter
|
||||||
def system_id(self, system_id):
|
def system_id(self, system_id):
|
||||||
"""
|
"""
|
||||||
Set the system ID.
|
Sets the system ID.
|
||||||
|
|
||||||
:param system_id: a system ID (also called board processor ID)
|
:param system_id: a system ID (also called board processor ID)
|
||||||
"""
|
"""
|
||||||
@ -832,6 +1030,11 @@ class Router(object):
|
|||||||
self._hypervisor.send("{platform} set_system_id {name} {system_id}".format(platform=self._platform,
|
self._hypervisor.send("{platform} set_system_id {name} {system_id}".format(platform=self._platform,
|
||||||
name=self._name,
|
name=self._name,
|
||||||
system_id=system_id))
|
system_id=system_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: system ID updated from {old_id} to {new_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
old_id=self._system_id,
|
||||||
|
new_id=system_id))
|
||||||
self._system_id = system_id
|
self._system_id = system_id
|
||||||
|
|
||||||
def get_hardware_info(self):
|
def get_hardware_info(self):
|
||||||
@ -841,7 +1044,7 @@ class Router(object):
|
|||||||
:returns: ? (could not test)
|
:returns: ? (could not test)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# FIXME: nothing returned by Dynamips.
|
# FIXME: nothing returned by Dynamips.
|
||||||
return (self._hypervisor.send("{platform} show_hardware {name}".format(platform=self._platform,
|
return (self._hypervisor.send("{platform} show_hardware {name}".format(platform=self._platform,
|
||||||
name=self._name)))
|
name=self._name)))
|
||||||
|
|
||||||
@ -856,7 +1059,7 @@ class Router(object):
|
|||||||
|
|
||||||
def slot_add_binding(self, slot_id, adapter):
|
def slot_add_binding(self, slot_id, adapter):
|
||||||
"""
|
"""
|
||||||
Adds a slot binding.
|
Adds a slot binding (a module into a slot).
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_id: slot ID
|
||||||
:param adapter: device to add in the corresponding slot (object)
|
:param adapter: device to add in the corresponding slot (object)
|
||||||
@ -877,6 +1080,12 @@ class Router(object):
|
|||||||
self._hypervisor.send("vm slot_add_binding {name} {slot_id} 0 {adapter}".format(name=self._name,
|
self._hypervisor.send("vm slot_add_binding {name} {slot_id} 0 {adapter}".format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
adapter=adapter))
|
adapter=adapter))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: adapter {adapter} inserted into slot {slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
adapter=adapter,
|
||||||
|
slot_id=slot_id))
|
||||||
|
|
||||||
self._slots[slot_id] = adapter
|
self._slots[slot_id] = adapter
|
||||||
|
|
||||||
# Generate an OIR event if the router is running and
|
# Generate an OIR event if the router is running and
|
||||||
@ -888,33 +1097,48 @@ class Router(object):
|
|||||||
self._hypervisor.send("vm slot_oir_start {name} {slot_id} 0".format(name=self._name,
|
self._hypervisor.send("vm slot_oir_start {name} {slot_id} 0".format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_id=slot_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: OIR start event sent to slot {slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
slot_id=slot_id))
|
||||||
|
|
||||||
def slot_remove_binding(self, slot_id):
|
def slot_remove_binding(self, slot_id):
|
||||||
"""
|
"""
|
||||||
Removes a slot binding.
|
Removes a slot binding (a module from a slot).
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_id: slot ID
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
slot = self._slots[slot_id]
|
adapter = self._slots[slot_id]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
|
raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_id=slot_id))
|
||||||
|
|
||||||
if slot == None:
|
if adapter == None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#FIXME: check if adapter can be removed!
|
||||||
|
|
||||||
# Generate an OIR event if the router is running and
|
# Generate an OIR event if the router is running and
|
||||||
# only for c7200, c3600 and c3745 (NM-4T only)
|
# only for c7200, c3600 and c3745 (NM-4T only)
|
||||||
if self.is_running() and self._platform == 'c7200' \
|
if self.is_running() and self._platform == 'c7200' \
|
||||||
or (self._platform == 'c3600' and self.chassis == '3660') \
|
or (self._platform == 'c3600' and self.chassis == '3660') \
|
||||||
or (self._platform == 'c3745' and slot == 'NM-4T'):
|
or (self._platform == 'c3745' and adapter == 'NM-4T'):
|
||||||
|
|
||||||
self._hypervisor.send("vm slot_oir_stop {name} {slot_id} 0".format(name=self._name,
|
self._hypervisor.send("vm slot_oir_stop {name} {slot_id} 0".format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_id=slot_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: OIR stop event sent to slot {slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
slot_id=slot_id))
|
||||||
|
|
||||||
self._hypervisor.send("vm slot_remove_binding {name} {slot_id} 0".format(name=self._name,
|
self._hypervisor.send("vm slot_remove_binding {name} {slot_id} 0".format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_id=slot_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: adapter {adapter} removed from slot {slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
adapter=adapter,
|
||||||
|
slot_id=slot_id))
|
||||||
self._slots[slot_id] = None
|
self._slots[slot_id] = None
|
||||||
|
|
||||||
def install_wic(self, wic_slot_id, wic):
|
def install_wic(self, wic_slot_id, wic):
|
||||||
@ -947,6 +1171,12 @@ class Router(object):
|
|||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
wic_slot_id=internal_wic_slot_id,
|
wic_slot_id=internal_wic_slot_id,
|
||||||
wic=wic))
|
wic=wic))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: {wic} inserted into WIC slot {wic_slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
wic=wic,
|
||||||
|
wic_slot_id=wic_slot_id))
|
||||||
|
|
||||||
adapter.install_wic(wic_slot_id, wic)
|
adapter.install_wic(wic_slot_id, wic)
|
||||||
|
|
||||||
def uninstall_wic(self, wic_slot_id):
|
def uninstall_wic(self, wic_slot_id):
|
||||||
@ -976,6 +1206,11 @@ class Router(object):
|
|||||||
self._hypervisor.send("vm slot_remove_binding {name} {slot_id} {wic_slot_id}".format(name=self._name,
|
self._hypervisor.send("vm slot_remove_binding {name} {slot_id} {wic_slot_id}".format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
wic_slot_id=internal_wic_slot_id))
|
wic_slot_id=internal_wic_slot_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: {wic} removed from WIC slot {wic_slot_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
wic=adapter.wics[wic_slot_id],
|
||||||
|
wic_slot_id=wic_slot_id))
|
||||||
adapter.uninstall_wic(wic_slot_id)
|
adapter.uninstall_wic(wic_slot_id)
|
||||||
|
|
||||||
def get_slot_nio_bindings(self, slot_id):
|
def get_slot_nio_bindings(self, slot_id):
|
||||||
@ -1012,6 +1247,13 @@ class Router(object):
|
|||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
port_id=port_id,
|
port_id=port_id,
|
||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: NIO {nio_name} bound to port {slot_id}/{port_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio_name=nio.name,
|
||||||
|
slot_id=slot_id,
|
||||||
|
port_id=port_id))
|
||||||
|
|
||||||
self.slot_enable_nio(slot_id, port_id)
|
self.slot_enable_nio(slot_id, port_id)
|
||||||
adapter.add_nio(port_id, nio)
|
adapter.add_nio(port_id, nio)
|
||||||
|
|
||||||
@ -1021,6 +1263,8 @@ class Router(object):
|
|||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_id: slot ID
|
||||||
:param port_id: port ID
|
:param port_id: port ID
|
||||||
|
|
||||||
|
:returns: removed NIO object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1033,12 +1277,21 @@ class Router(object):
|
|||||||
port_id=port_id))
|
port_id=port_id))
|
||||||
|
|
||||||
self.slot_disable_nio(slot_id, port_id)
|
self.slot_disable_nio(slot_id, port_id)
|
||||||
self._hypervisor.send("vm slot_remove_binding {name} {slot_id} {port_id}".format(name=self._name,
|
self._hypervisor.send("vm slot_remove_nio_binding {name} {slot_id} {port_id}".format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
port_id=port_id))
|
port_id=port_id))
|
||||||
|
|
||||||
|
nio = adapter.get_nio(port_id)
|
||||||
adapter.remove_nio(port_id)
|
adapter.remove_nio(port_id)
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: NIO {nio_name} removed from port {slot_id}/{port_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
nio_name=nio.name,
|
||||||
|
slot_id=slot_id,
|
||||||
|
port_id=port_id))
|
||||||
|
|
||||||
|
return nio
|
||||||
|
|
||||||
def slot_enable_nio(self, slot_id, port_id):
|
def slot_enable_nio(self, slot_id, port_id):
|
||||||
"""
|
"""
|
||||||
Enables a slot NIO binding.
|
Enables a slot NIO binding.
|
||||||
@ -1052,6 +1305,11 @@ class Router(object):
|
|||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
port_id=port_id))
|
port_id=port_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: NIO enabled on port {slot_id}/{port_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
slot_id=slot_id,
|
||||||
|
port_id=port_id))
|
||||||
|
|
||||||
def slot_disable_nio(self, slot_id, port_id):
|
def slot_disable_nio(self, slot_id, port_id):
|
||||||
"""
|
"""
|
||||||
Disables a slot NIO binding.
|
Disables a slot NIO binding.
|
||||||
@ -1065,6 +1323,11 @@ class Router(object):
|
|||||||
slot_id=slot_id,
|
slot_id=slot_id,
|
||||||
port_id=port_id))
|
port_id=port_id))
|
||||||
|
|
||||||
|
log.info("router {name} [id={id}]: NIO disabled on port {slot_id}/{port_id}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
slot_id=slot_id,
|
||||||
|
port_id=port_id))
|
||||||
|
|
||||||
def _create_slots(self, numslots):
|
def _create_slots(self, numslots):
|
||||||
"""
|
"""
|
||||||
Creates the appropriate number of slots for this router.
|
Creates the appropriate number of slots for this router.
|
||||||
|
@ -84,7 +84,7 @@ class Server(object):
|
|||||||
tornado_app = tornado.web.Application(self.handlers, debug=True) # FIXME: debug mode!
|
tornado_app = tornado.web.Application(self.handlers, debug=True) # FIXME: debug mode!
|
||||||
try:
|
try:
|
||||||
print("Starting server on port {}".format(self._port))
|
print("Starting server on port {}".format(self._port))
|
||||||
tornado_app.listen(self._port)
|
tornado_app.listen(self._port, address=self._host)
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.errno == errno.EADDRINUSE: # socket already in use
|
if e.errno == errno.EADDRINUSE: # socket already in use
|
||||||
logging.critical("socket in use for port {}".format(self._port))
|
logging.critical("socket in use for port {}".format(self._port))
|
||||||
@ -92,7 +92,7 @@ class Server(object):
|
|||||||
|
|
||||||
ioloop = tornado.ioloop.IOLoop.instance()
|
ioloop = tornado.ioloop.IOLoop.instance()
|
||||||
stream = zmqstream.ZMQStream(router, ioloop)
|
stream = zmqstream.ZMQStream(router, ioloop)
|
||||||
stream.on_recv(JSONRPCWebSocket.dispatch_message)
|
stream.on_recv_stream(JSONRPCWebSocket.dispatch_message)
|
||||||
tornado.autoreload.add_reload_hook(functools.partial(self._cleanup, stop=False))
|
tornado.autoreload.add_reload_hook(functools.partial(self._cleanup, stop=False))
|
||||||
|
|
||||||
def signal_handler(signum=None, frame=None):
|
def signal_handler(signum=None, frame=None):
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
# -*- 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/>.
|
|
||||||
|
|
||||||
#import networkx as nx
|
|
||||||
|
|
||||||
|
|
||||||
class Topology(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
pass
|
|
||||||
#self._topology = nx.Graph()
|
|
||||||
|
|
||||||
def add_node(self, node):
|
|
||||||
|
|
||||||
self._topology.add_node(node)
|
|
||||||
|
|
||||||
def remove_node(self, node):
|
|
||||||
|
|
||||||
self._topology.remove_node(node)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
|
|
||||||
self._topology.clear()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
|
|
||||||
return "GNS3 network topology"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def instance():
|
|
||||||
|
|
||||||
if not hasattr(Topology, "_instance"):
|
|
||||||
Topology._instance = Topology()
|
|
||||||
return Topology._instance
|
|
@ -1,2 +1,3 @@
|
|||||||
tornado
|
tornado
|
||||||
pyzmq
|
pyzmq
|
||||||
|
netifaces-py3
|
||||||
|
@ -36,7 +36,7 @@ class JSONRPC(AsyncTestCase):
|
|||||||
|
|
||||||
def test_request_with_invalid_version(self):
|
def test_request_with_invalid_version(self):
|
||||||
|
|
||||||
request = {"jsonrpc": "1.0", "method": "dynamips.echo", "id": 1}
|
request = {"jsonrpc": 1.0, "method": "dynamips.echo", "id": 1}
|
||||||
AsyncWSRequest(self.URL, self.io_loop, self.stop, json_encode(request))
|
AsyncWSRequest(self.URL, self.io_loop, self.stop, json_encode(request))
|
||||||
response = self.wait()
|
response = self.wait()
|
||||||
json_response = json_decode(response)
|
json_response = json_decode(response)
|
||||||
|
Loading…
Reference in New Issue
Block a user