mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
186 files changed
+1173
-1206
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,423 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual ATM switch module ("atmsw").
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import re
|
||||
|
||||
from .device import Device
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ATMSwitch(Device):
|
||||
|
||||
"""
|
||||
Dynamips ATM switch.
|
||||
|
||||
:param name: name for this switch
|
||||
:param device_id: Device instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
||||
|
||||
super().__init__(name, device_id, project, manager, hypervisor)
|
||||
self._nios = {}
|
||||
self._mappings = {}
|
||||
|
||||
def __json__(self):
|
||||
|
||||
mappings = {}
|
||||
for source, destination in self._mappings.items():
|
||||
mappings[str(source)] = str(destination)
|
||||
|
||||
return {"name": self.name,
|
||||
"device_id": self.id,
|
||||
"project_id": self.project.id,
|
||||
"mappings": mappings}
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
if self._hypervisor is None:
|
||||
module_workdir = self.project.module_working_directory(self.manager.module_name.lower())
|
||||
self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir)
|
||||
|
||||
yield from self._hypervisor.send('atmsw create "{}"'.format(self._name))
|
||||
log.info('ATM switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||
self._hypervisor.devices.append(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_name(self, new_name):
|
||||
"""
|
||||
Renames this ATM switch.
|
||||
|
||||
:param new_name: New name for this switch
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('atm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name))
|
||||
log.info('ATM switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name,
|
||||
id=self._id,
|
||||
new_name=new_name))
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def nios(self):
|
||||
"""
|
||||
Returns all the NIOs member of this ATM switch.
|
||||
|
||||
:returns: nio list
|
||||
"""
|
||||
|
||||
return self._nios
|
||||
|
||||
@property
|
||||
def mappings(self):
|
||||
"""
|
||||
Returns port mappings
|
||||
|
||||
:returns: mappings list
|
||||
"""
|
||||
|
||||
return self._mappings
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this ATM switch.
|
||||
"""
|
||||
|
||||
for nio in self._nios.values():
|
||||
if nio and isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
try:
|
||||
yield from self._hypervisor.send('atmsw delete "{}"'.format(self._name))
|
||||
log.info('ATM switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id))
|
||||
except DynamipsError:
|
||||
log.debug("Could not properly delete ATM switch {}".format(self._name))
|
||||
if self._hypervisor and self in self._hypervisor.devices:
|
||||
self._hypervisor.devices.remove(self)
|
||||
if self._hypervisor and not self._hypervisor.devices:
|
||||
yield from self.hypervisor.stop()
|
||||
|
||||
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_number):
|
||||
"""
|
||||
Adds a NIO as new port on ATM switch.
|
||||
|
||||
:param nio: NIO instance to add
|
||||
:param port_number: port to allocate for the NIO
|
||||
"""
|
||||
|
||||
if port_number in self._nios:
|
||||
raise DynamipsError("Port {} isn't free".format(port_number))
|
||||
|
||||
log.info('ATM switch "{name}" [id={id}]: NIO {nio} bound to port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
self._nios[port_number] = nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_nio(self, port_number):
|
||||
"""
|
||||
Removes the specified NIO as member of this ATM switch.
|
||||
|
||||
:param port_number: allocated port number
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
# remove VCs mapped with the port
|
||||
for source, destination in self._mappings.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_number == source_port:
|
||||
yield from self.unmap_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
|
||||
yield from self.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_number == source_port:
|
||||
yield from self.unmap_vp(source_port, source_vpi, destination_port, destination_vpi)
|
||||
yield from self.unmap_vp(destination_port, destination_vpi, source_port, source_vpi)
|
||||
|
||||
nio = self._nios[port_number]
|
||||
if isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
log.info('ATM switch "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
del self._nios[port_number]
|
||||
return nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_mappings(self, mappings):
|
||||
"""
|
||||
Applies VC mappings
|
||||
|
||||
:param mappings: mappings (dict)
|
||||
"""
|
||||
|
||||
pvc_entry = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
|
||||
for source, destination in mappings.items():
|
||||
if not isinstance(source, str) or not isinstance(destination, str):
|
||||
raise DynamipsError("Invalid ATM mappings")
|
||||
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
|
||||
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 self.has_port(destination_port):
|
||||
if (source_port, source_vpi, source_vci) not in self.mappings and \
|
||||
(destination_port, destination_vpi, destination_vci) not in self.mappings:
|
||||
yield from self.map_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
|
||||
yield from self.map_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci)
|
||||
else:
|
||||
# add the virtual paths
|
||||
source_port, source_vpi = map(int, source.split(':'))
|
||||
destination_port, destination_vpi = map(int, destination.split(':'))
|
||||
if self.has_port(destination_port):
|
||||
if (source_port, source_vpi) not in self.mappings and (destination_port, destination_vpi) not in self.mappings:
|
||||
yield from self.map_vp(source_port, source_vpi, destination_port, destination_vpi)
|
||||
yield from self.map_vp(destination_port, destination_vpi, source_port, source_vpi)
|
||||
|
||||
@asyncio.coroutine
|
||||
def map_vp(self, port1, vpi1, port2, vpi2):
|
||||
"""
|
||||
Creates a new Virtual Path connection.
|
||||
|
||||
:param port1: input port
|
||||
:param vpi1: input vpi
|
||||
:param port2: output port
|
||||
:param vpi2: output vpi
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('atmsw create_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_vpi=vpi1,
|
||||
output_nio=nio2,
|
||||
output_vpi=vpi2))
|
||||
|
||||
log.info('ATM switch "{name}" [{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._mappings[(port1, vpi1)] = (port2, vpi2)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unmap_vp(self, port1, vpi1, port2, vpi2):
|
||||
"""
|
||||
Deletes a new Virtual Path connection.
|
||||
|
||||
:param port1: input port
|
||||
:param vpi1: input vpi
|
||||
:param port2: output port
|
||||
:param vpi2: output vpi
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('atmsw delete_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_vpi=vpi1,
|
||||
output_nio=nio2,
|
||||
output_vpi=vpi2))
|
||||
|
||||
log.info('ATM switch "{name}" [{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._mappings[(port1, vpi1)]
|
||||
|
||||
@asyncio.coroutine
|
||||
def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
||||
"""
|
||||
Creates a new Virtual Channel connection (unidirectional).
|
||||
|
||||
:param port1: input port
|
||||
:param vpi1: input vpi
|
||||
:param vci1: input vci
|
||||
:param port2: output port
|
||||
:param vpi2: output vpi
|
||||
:param vci2: output vci
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('atmsw create_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_vpi=vpi1,
|
||||
input_vci=vci1,
|
||||
output_nio=nio2,
|
||||
output_vpi=vpi2,
|
||||
output_vci=vci2))
|
||||
|
||||
log.info('ATM switch "{name}" [{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._mappings[(port1, vpi1, vci1)] = (port2, vpi2, vci2)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
|
||||
"""
|
||||
Deletes a new Virtual Channel connection (unidirectional).
|
||||
|
||||
:param port1: input port
|
||||
:param vpi1: input vpi
|
||||
:param vci1: input vci
|
||||
:param port2: output port
|
||||
:param vpi2: output vpi
|
||||
:param vci2: output vci
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('atmsw delete_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_vpi=vpi1,
|
||||
input_vci=vci1,
|
||||
output_nio=nio2,
|
||||
output_vpi=vpi2,
|
||||
output_vci=vci2))
|
||||
|
||||
log.info('ATM switch "{name}" [{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._mappings[(port1, vpi1, vci1)]
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_capture(self, port_number, output_file, data_link_type="DLT_ATM_RFC1483"):
|
||||
"""
|
||||
Starts a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param output_file: PCAP destination file for the capture
|
||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_ATM_RFC1483
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
|
||||
data_link_type = data_link_type.lower()
|
||||
if data_link_type.startswith("dlt_"):
|
||||
data_link_type = data_link_type[4:]
|
||||
|
||||
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||
raise DynamipsError("Port {} has already a filter applied".format(port_number))
|
||||
|
||||
yield from nio.bind_filter("both", "capture")
|
||||
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
||||
|
||||
log.info('ATM switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
|
||||
@asyncio.coroutine
|
||||
def stop_capture(self, port_number):
|
||||
"""
|
||||
Stops a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
yield from nio.unbind_filter("both")
|
||||
log.info('ATM switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
@@ -0,0 +1,108 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips NIO bridge module ("nio_bridge").
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L538
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .device import Device
|
||||
|
||||
|
||||
class Bridge(Device):
|
||||
|
||||
"""
|
||||
Dynamips bridge.
|
||||
|
||||
:param name: name for this bridge
|
||||
:param node_id: Node instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, node_id, project, manager, hypervisor=None):
|
||||
|
||||
super().__init__(name, node_id, project, manager, hypervisor)
|
||||
self._nios = []
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
if self._hypervisor is None:
|
||||
module_workdir = self.project.module_working_directory(self.manager.module_name.lower())
|
||||
self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir)
|
||||
|
||||
yield from self._hypervisor.send('nio_bridge create "{}"'.format(self._name))
|
||||
self._hypervisor.devices.append(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_name(self, new_name):
|
||||
"""
|
||||
Renames this bridge.
|
||||
|
||||
:param new_name: New name for this bridge
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('nio_bridge rename "{name}" "{new_name}"'.format(name=self._name,
|
||||
new_name=new_name))
|
||||
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def nios(self):
|
||||
"""
|
||||
Returns all the NIOs member of this bridge.
|
||||
|
||||
:returns: nio list
|
||||
"""
|
||||
|
||||
return self._nios
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this bridge.
|
||||
"""
|
||||
|
||||
if self._hypervisor and self in self._hypervisor.devices:
|
||||
self._hypervisor.devices.remove(self)
|
||||
if self._hypervisor and not self._hypervisor.devices:
|
||||
yield from self._hypervisor.send('nio_bridge delete "{}"'.format(self._name))
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_nio(self, nio):
|
||||
"""
|
||||
Adds a NIO as new port on this bridge.
|
||||
|
||||
:param nio: NIO instance to add
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('nio_bridge add_nio "{name}" {nio}'.format(name=self._name, nio=nio))
|
||||
self._nios.append(nio)
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_nio(self, nio):
|
||||
"""
|
||||
Removes the specified NIO as member of this bridge.
|
||||
|
||||
:param nio: NIO instance to remove
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('nio_bridge remove_nio "{name}" {nio}'.format(name=self._name, nio=nio))
|
||||
self._nios.remove(nio)
|
||||
@@ -0,0 +1,148 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 1700 instances module ("c1700")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L428
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.c1700_mb_1fe import C1700_MB_1FE
|
||||
from ..adapters.c1700_mb_wic1 import C1700_MB_WIC1
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C1700(Router):
|
||||
|
||||
"""
|
||||
Dynamips c1700 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
:param chassis: chassis for this router:
|
||||
1720, 1721, 1750, 1751 or 1760 (default = 1720).
|
||||
1710 is not supported.
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c1700")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 64
|
||||
self._nvram = 32
|
||||
self._disk0 = 0
|
||||
self._disk1 = 0
|
||||
self._chassis = chassis
|
||||
self._iomem = 15 # percentage
|
||||
self._clock_divisor = 8
|
||||
self._sparsemem = False # never activate sparsemem for c1700 (unstable)
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c1700_router_info = {"iomem": self._iomem,
|
||||
"chassis": self._chassis,
|
||||
"sparsemem": self._sparsemem}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c1700_router_info)
|
||||
return router_info
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
yield from Router.create(self)
|
||||
if self._chassis != "1720":
|
||||
yield from self.set_chassis(self._chassis)
|
||||
self._setup_chassis()
|
||||
|
||||
def _setup_chassis(self):
|
||||
"""
|
||||
Sets up the router with the corresponding chassis
|
||||
(create slots and insert default adapters).
|
||||
"""
|
||||
|
||||
# With 1751 and 1760, WICs in WIC slot 1 show up as in slot 1, not 0
|
||||
# e.g. s1/0 not s0/2
|
||||
if self._chassis in ['1751', '1760']:
|
||||
self._create_slots(2)
|
||||
self._slots[1] = C1700_MB_WIC1()
|
||||
else:
|
||||
self._create_slots(1)
|
||||
self._slots[0] = C1700_MB_1FE()
|
||||
|
||||
@property
|
||||
def chassis(self):
|
||||
"""
|
||||
Returns the chassis.
|
||||
|
||||
:returns: chassis string
|
||||
"""
|
||||
|
||||
return self._chassis
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_chassis(self, chassis):
|
||||
"""
|
||||
Sets the chassis.
|
||||
|
||||
:param: chassis string:
|
||||
1720, 1721, 1750, 1751 or 1760
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c1700 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis))
|
||||
|
||||
log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name,
|
||||
id=self._id,
|
||||
chassis=chassis))
|
||||
|
||||
self._chassis = chassis
|
||||
self._setup_chassis()
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Sets I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c1700 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,157 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 2600 instances module ("c2600")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L404
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.c2600_mb_1e import C2600_MB_1E
|
||||
from ..adapters.c2600_mb_2e import C2600_MB_2E
|
||||
from ..adapters.c2600_mb_1fe import C2600_MB_1FE
|
||||
from ..adapters.c2600_mb_2fe import C2600_MB_2FE
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C2600(Router):
|
||||
|
||||
"""
|
||||
Dynamips c2600 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
:param chassis: chassis for this router:
|
||||
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
||||
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
|
||||
"""
|
||||
|
||||
# adapters to insert by default corresponding the
|
||||
# chosen chassis.
|
||||
integrated_adapters = {"2610": C2600_MB_1E,
|
||||
"2611": C2600_MB_2E,
|
||||
"2620": C2600_MB_1FE,
|
||||
"2621": C2600_MB_2FE,
|
||||
"2610XM": C2600_MB_1FE,
|
||||
"2611XM": C2600_MB_2FE,
|
||||
"2620XM": C2600_MB_1FE,
|
||||
"2621XM": C2600_MB_2FE,
|
||||
"2650XM": C2600_MB_1FE,
|
||||
"2651XM": C2600_MB_2FE}
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="2610"):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2600")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 64
|
||||
self._nvram = 128
|
||||
self._disk0 = 0
|
||||
self._disk1 = 0
|
||||
self._chassis = chassis
|
||||
self._iomem = 15 # percentage
|
||||
self._clock_divisor = 8
|
||||
self._sparsemem = False # never activate sparsemem for c2600 (unstable)
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c2600_router_info = {"iomem": self._iomem,
|
||||
"chassis": self._chassis,
|
||||
"sparsemem": self._sparsemem}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c2600_router_info)
|
||||
return router_info
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
yield from Router.create(self)
|
||||
if self._chassis != "2610":
|
||||
yield from self.set_chassis(self._chassis)
|
||||
self._setup_chassis()
|
||||
|
||||
def _setup_chassis(self):
|
||||
"""
|
||||
Sets up the router with the corresponding chassis
|
||||
(create slots and insert default adapters).
|
||||
"""
|
||||
|
||||
self._create_slots(2)
|
||||
self._slots[0] = self.integrated_adapters[self._chassis]()
|
||||
|
||||
@property
|
||||
def chassis(self):
|
||||
"""
|
||||
Returns the chassis.
|
||||
|
||||
:returns: chassis string
|
||||
"""
|
||||
|
||||
return self._chassis
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_chassis(self, chassis):
|
||||
"""
|
||||
Sets the chassis.
|
||||
|
||||
:param: chassis string:
|
||||
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
||||
2620XM, 2621XM, 2650XM or 2651XM
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c2600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis))
|
||||
|
||||
log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name,
|
||||
id=self._id,
|
||||
chassis=chassis))
|
||||
self._chassis = chassis
|
||||
self._setup_chassis()
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Sets I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c2600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 2691 instances module ("c2691")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L387
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.gt96100_fe import GT96100_FE
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C2691(Router):
|
||||
|
||||
"""
|
||||
Dynamips c2691 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2691")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 128
|
||||
self._nvram = 112
|
||||
self._disk0 = 16
|
||||
self._disk1 = 0
|
||||
self._iomem = 5 # percentage
|
||||
self._clock_divisor = 8
|
||||
|
||||
self._create_slots(2)
|
||||
self._slots[0] = GT96100_FE()
|
||||
|
||||
if chassis is not None:
|
||||
raise DynamipsError("c2691 routers do not have chassis")
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c2691_router_info = {"iomem": self._iomem}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c2691_router_info)
|
||||
return router_info
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Sets I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c2691 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,142 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 3600 instances module ("c3600")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L366
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.leopard_2fe import Leopard_2FE
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C3600(Router):
|
||||
|
||||
"""
|
||||
Dynamips c3600 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
:param chassis: chassis for this router:
|
||||
3620, 3640 or 3660 (default = 3640).
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3600")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 128
|
||||
self._nvram = 128
|
||||
self._disk0 = 0
|
||||
self._disk1 = 0
|
||||
self._iomem = 5 # percentage
|
||||
self._chassis = chassis
|
||||
self._clock_divisor = 4
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c3600_router_info = {"iomem": self._iomem,
|
||||
"chassis": self._chassis}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c3600_router_info)
|
||||
return router_info
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
yield from Router.create(self)
|
||||
if self._chassis != "3640":
|
||||
yield from self.set_chassis(self._chassis)
|
||||
self._setup_chassis()
|
||||
|
||||
def _setup_chassis(self):
|
||||
"""
|
||||
Sets up the router with the corresponding chassis
|
||||
(create slots and insert default adapters).
|
||||
"""
|
||||
|
||||
if self._chassis == "3620":
|
||||
self._create_slots(2)
|
||||
elif self._chassis == "3640":
|
||||
self._create_slots(4)
|
||||
elif self._chassis == "3660":
|
||||
self._create_slots(7)
|
||||
self._slots[0] = Leopard_2FE()
|
||||
|
||||
@property
|
||||
def chassis(self):
|
||||
"""
|
||||
Returns the chassis.
|
||||
|
||||
:returns: chassis string
|
||||
"""
|
||||
|
||||
return self._chassis
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_chassis(self, chassis):
|
||||
"""
|
||||
Sets the chassis.
|
||||
|
||||
:param: chassis string: 3620, 3640 or 3660
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c3600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis))
|
||||
|
||||
log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name,
|
||||
id=self._id,
|
||||
chassis=chassis))
|
||||
|
||||
self._chassis = chassis
|
||||
self._setup_chassis()
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Set I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c3600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 3725 instances module ("c3725")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L346
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.gt96100_fe import GT96100_FE
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C3725(Router):
|
||||
|
||||
"""
|
||||
Dynamips c3725 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3725")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 128
|
||||
self._nvram = 112
|
||||
self._disk0 = 16
|
||||
self._disk1 = 0
|
||||
self._iomem = 5 # percentage
|
||||
self._clock_divisor = 8
|
||||
|
||||
self._create_slots(3)
|
||||
self._slots[0] = GT96100_FE()
|
||||
|
||||
if chassis is not None:
|
||||
raise DynamipsError("c3725 routers do not have chassis")
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c3725_router_info = {"iomem": self._iomem}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c3725_router_info)
|
||||
return router_info
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Sets I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c3725 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 3745 instances module ("c3745")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L326
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from .router import Router
|
||||
from ..adapters.gt96100_fe import GT96100_FE
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C3745(Router):
|
||||
|
||||
"""
|
||||
Dynamips c3745 router.
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3745")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 128
|
||||
self._nvram = 304
|
||||
self._disk0 = 16
|
||||
self._disk1 = 0
|
||||
self._iomem = 5 # percentage
|
||||
self._clock_divisor = 8
|
||||
|
||||
self._create_slots(5)
|
||||
self._slots[0] = GT96100_FE()
|
||||
|
||||
if chassis is not None:
|
||||
raise DynamipsError("c3745 routers do not have chassis")
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c3745_router_info = {"iomem": self._iomem}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c3745_router_info)
|
||||
return router_info
|
||||
|
||||
@property
|
||||
def iomem(self):
|
||||
"""
|
||||
Returns I/O memory size for this router.
|
||||
|
||||
:returns: I/O memory size (integer)
|
||||
"""
|
||||
|
||||
return self._iomem
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_iomem(self, iomem):
|
||||
"""
|
||||
Sets I/O memory size for this router.
|
||||
|
||||
:param iomem: I/O memory size
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c3745 set_iomem "{name}" {size}'.format(name=self._name, size=iomem))
|
||||
|
||||
log.info('Router "{name}" [{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
|
||||
@@ -0,0 +1,244 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Cisco 7200 instances module ("c7200")
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L294
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from .router import Router
|
||||
from ..adapters.c7200_io_fe import C7200_IO_FE
|
||||
from ..adapters.c7200_io_ge_e import C7200_IO_GE_E
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class C7200(Router):
|
||||
|
||||
"""
|
||||
Dynamips c7200 router (model is 7206).
|
||||
|
||||
:param name: The name of this router
|
||||
:param vm_id: Router instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param dynamips_id: ID to use with Dynamips
|
||||
:param console: console port
|
||||
:param aux: auxiliary console port
|
||||
:param npe: Default NPE
|
||||
"""
|
||||
|
||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, npe="npe-400", chassis=None):
|
||||
|
||||
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c7200")
|
||||
|
||||
# Set default values for this platform (must be the same as Dynamips)
|
||||
self._ram = 256
|
||||
self._nvram = 128
|
||||
self._disk0 = 64
|
||||
self._disk1 = 0
|
||||
self._npe = npe
|
||||
self._midplane = "vxr"
|
||||
self._clock_divisor = 4
|
||||
self._npe = npe
|
||||
|
||||
# 4 sensors with a default temperature of 22C:
|
||||
# sensor 1 = I/0 controller inlet
|
||||
# sensor 2 = I/0 controller outlet
|
||||
# sensor 3 = NPE inlet
|
||||
# sensor 4 = NPE outlet
|
||||
self._sensors = [22, 22, 22, 22]
|
||||
|
||||
# 2 power supplies powered on
|
||||
self._power_supplies = [1, 1]
|
||||
|
||||
self._create_slots(7)
|
||||
|
||||
if chassis is not None:
|
||||
raise DynamipsError("c7200 routers do not have chassis")
|
||||
|
||||
def __json__(self):
|
||||
|
||||
c7200_router_info = {"npe": self._npe,
|
||||
"midplane": self._midplane,
|
||||
"sensors": self._sensors,
|
||||
"power_supplies": self._power_supplies}
|
||||
|
||||
router_info = Router.__json__(self)
|
||||
router_info.update(c7200_router_info)
|
||||
return router_info
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
yield from Router.create(self)
|
||||
|
||||
if self._npe != "npe-400":
|
||||
yield from self.set_npe(self._npe)
|
||||
|
||||
# first slot is a mandatory Input/Output controller (based on NPE type)
|
||||
if self.npe == "npe-g2":
|
||||
yield from self.slot_add_binding(0, C7200_IO_GE_E())
|
||||
else:
|
||||
yield from self.slot_add_binding(0, C7200_IO_FE())
|
||||
|
||||
@property
|
||||
def npe(self):
|
||||
"""
|
||||
Returns the NPE model.
|
||||
|
||||
:returns: NPE model string (e.g. "npe-200")
|
||||
"""
|
||||
|
||||
return self._npe
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_npe(self, npe):
|
||||
"""
|
||||
Sets the NPE model.
|
||||
|
||||
:params npe: NPE model string (e.g. "npe-200")
|
||||
NPE models are npe-100, npe-150, npe-175, npe-200,
|
||||
npe-225, npe-300, npe-400 and npe-g2 (PowerPC c7200 only)
|
||||
"""
|
||||
|
||||
if (yield from self.is_running()):
|
||||
raise DynamipsError("Cannot change NPE on running router")
|
||||
|
||||
yield from self._hypervisor.send('c7200 set_npe "{name}" {npe}'.format(name=self._name, npe=npe))
|
||||
|
||||
log.info('Router "{name}" [{id}]: NPE updated from {old_npe} to {new_npe}'.format(name=self._name,
|
||||
id=self._id,
|
||||
old_npe=self._npe,
|
||||
new_npe=npe))
|
||||
self._npe = npe
|
||||
|
||||
@property
|
||||
def midplane(self):
|
||||
"""
|
||||
Returns the midplane model.
|
||||
|
||||
:returns: midplane model string (e.g. "vxr" or "std")
|
||||
"""
|
||||
|
||||
return self._midplane
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_midplane(self, midplane):
|
||||
"""
|
||||
Sets the midplane model.
|
||||
|
||||
:returns: midplane model string (e.g. "vxr" or "std")
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('c7200 set_midplane "{name}" {midplane}'.format(name=self._name, midplane=midplane))
|
||||
|
||||
log.info('Router "{name}" [{id}]: midplane updated from {old_midplane} to {new_midplane}'.format(name=self._name,
|
||||
id=self._id,
|
||||
old_midplane=self._midplane,
|
||||
new_midplane=midplane))
|
||||
self._midplane = midplane
|
||||
|
||||
@property
|
||||
def sensors(self):
|
||||
"""
|
||||
Returns the 4 sensors with temperature in degree Celcius.
|
||||
|
||||
:returns: list of 4 sensor temperatures
|
||||
"""
|
||||
|
||||
return self._sensors
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_sensors(self, sensors):
|
||||
"""
|
||||
Sets the 4 sensors with temperature in degree Celcius.
|
||||
|
||||
:param sensors: list of 4 sensor temperatures corresponding to
|
||||
sensor 1 = I/0 controller inlet
|
||||
sensor 2 = I/0 controller outlet
|
||||
sensor 3 = NPE inlet
|
||||
sensor 4 = NPE outlet
|
||||
Example: [22, 22, 22, 22]
|
||||
"""
|
||||
|
||||
sensor_id = 0
|
||||
for sensor in sensors:
|
||||
yield from self._hypervisor.send('c7200 set_temp_sensor "{name}" {sensor_id} {temp}'.format(name=self._name,
|
||||
sensor_id=sensor_id,
|
||||
temp=sensor))
|
||||
|
||||
log.info('Router "{name}" [{id}]: sensor {sensor_id} temperature updated from {old_temp}C to {new_temp}C'.format(name=self._name,
|
||||
id=self._id,
|
||||
sensor_id=sensor_id,
|
||||
old_temp=self._sensors[sensor_id],
|
||||
new_temp=sensors[sensor_id]))
|
||||
|
||||
sensor_id += 1
|
||||
self._sensors = sensors
|
||||
|
||||
@property
|
||||
def power_supplies(self):
|
||||
"""
|
||||
Returns the 2 power supplies with 0 = off, 1 = on.
|
||||
|
||||
:returns: list of 2 power supplies.
|
||||
"""
|
||||
|
||||
return self._power_supplies
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_power_supplies(self, power_supplies):
|
||||
"""
|
||||
Sets the 2 power supplies with 0 = off, 1 = on.
|
||||
|
||||
:param power_supplies: list of 2 power supplies.
|
||||
Example: [1, 0] = first power supply is on, second is off.
|
||||
"""
|
||||
|
||||
power_supply_id = 0
|
||||
for power_supply in power_supplies:
|
||||
yield from self._hypervisor.send('c7200 set_power_supply "{name}" {power_supply_id} {powered_on}'.format(name=self._name,
|
||||
power_supply_id=power_supply_id,
|
||||
powered_on=power_supply))
|
||||
|
||||
log.info('Router "{name}" [{id}]: power supply {power_supply_id} state updated to {powered_on}'.format(name=self._name,
|
||||
id=self._id,
|
||||
power_supply_id=power_supply_id,
|
||||
powered_on=power_supply))
|
||||
power_supply_id += 1
|
||||
|
||||
self._power_supplies = power_supplies
|
||||
|
||||
@asyncio.coroutine
|
||||
def start(self):
|
||||
"""
|
||||
Starts this router.
|
||||
At least the IOS image must be set before starting it.
|
||||
"""
|
||||
|
||||
# trick: we must send sensors and power supplies info after starting the router
|
||||
# otherwise they are not taken into account (Dynamips bug?)
|
||||
yield from Router.start(self)
|
||||
if self._sensors != [22, 22, 22, 22]:
|
||||
yield from self.set_sensors(self._sensors)
|
||||
if self._power_supplies != [1, 1]:
|
||||
yield from self.set_power_supplies(self._power_supplies)
|
||||
@@ -0,0 +1,104 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Device:
|
||||
|
||||
"""
|
||||
Base device for switches and hubs
|
||||
|
||||
:param name: name for this device
|
||||
:param device_id: Device instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
||||
|
||||
self._name = name
|
||||
self._id = device_id
|
||||
self._project = project
|
||||
self._manager = manager
|
||||
self._hypervisor = hypervisor
|
||||
|
||||
@property
|
||||
def hypervisor(self):
|
||||
"""
|
||||
Returns the current hypervisor.
|
||||
|
||||
:returns: hypervisor instance
|
||||
"""
|
||||
|
||||
return self._hypervisor
|
||||
|
||||
@property
|
||||
def project(self):
|
||||
"""
|
||||
Returns the device current project.
|
||||
|
||||
:returns: Project instance.
|
||||
"""
|
||||
|
||||
return self._project
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Returns the name for this device.
|
||||
|
||||
:returns: name
|
||||
"""
|
||||
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, new_name):
|
||||
"""
|
||||
Sets the name of this VM.
|
||||
|
||||
:param new_name: name
|
||||
"""
|
||||
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Returns the ID for this device.
|
||||
|
||||
:returns: device identifier (string)
|
||||
"""
|
||||
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def manager(self):
|
||||
"""
|
||||
Returns the manager for this device.
|
||||
|
||||
:returns: instance of manager
|
||||
"""
|
||||
|
||||
return self._manager
|
||||
|
||||
def create(self):
|
||||
"""
|
||||
Creates the device.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
@@ -0,0 +1,179 @@
|
||||
# -*- 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/>.
|
||||
|
||||
"""
|
||||
Hub object that uses the Bridge interface to create a hub with ports.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from .bridge import Bridge
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EthernetHub(Bridge):
|
||||
|
||||
"""
|
||||
Dynamips Ethernet hub (based on Bridge)
|
||||
|
||||
:param name: name for this hub
|
||||
:param device_id: Device instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
||||
|
||||
super().__init__(name, device_id, project, manager, hypervisor)
|
||||
self._mappings = {}
|
||||
|
||||
def __json__(self):
|
||||
|
||||
return {"name": self.name,
|
||||
"device_id": self.id,
|
||||
"project_id": self.project.id}
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
yield from Bridge.create(self)
|
||||
log.info('Ethernet hub "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||
|
||||
@property
|
||||
def mappings(self):
|
||||
"""
|
||||
Returns port mappings
|
||||
|
||||
:returns: mappings list
|
||||
"""
|
||||
|
||||
return self._mappings
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this hub.
|
||||
"""
|
||||
|
||||
for nio in self._nios:
|
||||
if nio and isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
try:
|
||||
yield from Bridge.delete(self)
|
||||
log.info('Ethernet hub "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id))
|
||||
except DynamipsError:
|
||||
log.debug("Could not properly delete Ethernet hub {}".format(self._name))
|
||||
if self._hypervisor and not self._hypervisor.devices:
|
||||
yield from self.hypervisor.stop()
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_nio(self, nio, port_number):
|
||||
"""
|
||||
Adds a NIO as new port on this hub.
|
||||
|
||||
:param nio: NIO instance to add
|
||||
:param port_number: port to allocate for the NIO
|
||||
"""
|
||||
|
||||
if port_number in self._mappings:
|
||||
raise DynamipsError("Port {} isn't free".format(port_number))
|
||||
|
||||
yield from Bridge.add_nio(self, nio)
|
||||
|
||||
log.info('Ethernet hub "{name}" [{id}]: NIO {nio} bound to port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
self._mappings[port_number] = nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_nio(self, port_number):
|
||||
"""
|
||||
Removes the specified NIO as member of this hub.
|
||||
|
||||
:param port_number: allocated port number
|
||||
|
||||
:returns: the NIO that was bound to the allocated port
|
||||
"""
|
||||
|
||||
if port_number not in self._mappings:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._mappings[port_number]
|
||||
if isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
yield from Bridge.remove_nio(self, nio)
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
del self._mappings[port_number]
|
||||
return nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"):
|
||||
"""
|
||||
Starts a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param output_file: PCAP destination file for the capture
|
||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||
"""
|
||||
|
||||
if port_number not in self._mappings:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._mappings[port_number]
|
||||
|
||||
data_link_type = data_link_type.lower()
|
||||
if data_link_type.startswith("dlt_"):
|
||||
data_link_type = data_link_type[4:]
|
||||
|
||||
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||
raise DynamipsError("Port {} has already a filter applied".format(port_number))
|
||||
|
||||
yield from nio.bind_filter("both", "capture")
|
||||
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
||||
|
||||
log.info('Ethernet hub "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
|
||||
@asyncio.coroutine
|
||||
def stop_capture(self, port_number):
|
||||
"""
|
||||
Stops a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
"""
|
||||
|
||||
if port_number not in self._mappings:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._mappings[port_number]
|
||||
yield from nio.unbind_filter("both")
|
||||
log.info('Ethernet hub "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
@@ -0,0 +1,343 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Ethernet switch module ("ethsw").
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from pkg_resources import parse_version
|
||||
|
||||
from .device import Device
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EthernetSwitch(Device):
|
||||
|
||||
"""
|
||||
Dynamips Ethernet switch.
|
||||
|
||||
:param name: name for this switch
|
||||
:param device_id: Device instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
||||
|
||||
super().__init__(name, device_id, project, manager, hypervisor)
|
||||
self._nios = {}
|
||||
self._mappings = {}
|
||||
|
||||
def __json__(self):
|
||||
|
||||
ethernet_switch_info = {"name": self.name,
|
||||
"device_id": self.id,
|
||||
"project_id": self.project.id}
|
||||
|
||||
ports = []
|
||||
for port_number, settings in self._mappings.items():
|
||||
ports.append({"port": port_number,
|
||||
"type": settings[0],
|
||||
"vlan": settings[1],
|
||||
"ethertype": settings[2] if len(settings) > 2 else ""})
|
||||
|
||||
ethernet_switch_info["ports"] = ports
|
||||
return ethernet_switch_info
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
if self._hypervisor is None:
|
||||
module_workdir = self.project.module_working_directory(self.manager.module_name.lower())
|
||||
self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir)
|
||||
|
||||
yield from self._hypervisor.send('ethsw create "{}"'.format(self._name))
|
||||
log.info('Ethernet switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||
self._hypervisor.devices.append(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_name(self, new_name):
|
||||
"""
|
||||
Renames this Ethernet switch.
|
||||
|
||||
:param new_name: New name for this switch
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('ethsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name))
|
||||
log.info('Ethernet switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name,
|
||||
id=self._id,
|
||||
new_name=new_name))
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def nios(self):
|
||||
"""
|
||||
Returns all the NIOs member of this Ethernet switch.
|
||||
|
||||
:returns: nio list
|
||||
"""
|
||||
|
||||
return self._nios
|
||||
|
||||
@property
|
||||
def mappings(self):
|
||||
"""
|
||||
Returns port mappings
|
||||
|
||||
:returns: mappings list
|
||||
"""
|
||||
|
||||
return self._mappings
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this Ethernet switch.
|
||||
"""
|
||||
|
||||
for nio in self._nios.values():
|
||||
if nio and isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
try:
|
||||
yield from self._hypervisor.send('ethsw delete "{}"'.format(self._name))
|
||||
log.info('Ethernet switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id))
|
||||
except DynamipsError:
|
||||
log.debug("Could not properly delete Ethernet switch {}".format(self._name))
|
||||
if self._hypervisor and self in self._hypervisor.devices:
|
||||
self._hypervisor.devices.remove(self)
|
||||
if self._hypervisor and not self._hypervisor.devices:
|
||||
yield from self.hypervisor.stop()
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_nio(self, nio, port_number):
|
||||
"""
|
||||
Adds a NIO as new port on Ethernet switch.
|
||||
|
||||
:param nio: NIO instance to add
|
||||
:param port_number: port to allocate for the NIO
|
||||
"""
|
||||
|
||||
if port_number in self._nios:
|
||||
raise DynamipsError("Port {} isn't free".format(port_number))
|
||||
|
||||
yield from self._hypervisor.send('ethsw add_nio "{name}" {nio}'.format(name=self._name, nio=nio))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: NIO {nio} bound to port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
self._nios[port_number] = nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_nio(self, port_number):
|
||||
"""
|
||||
Removes the specified NIO as member of this Ethernet switch.
|
||||
|
||||
:param port_number: allocated port number
|
||||
|
||||
:returns: the NIO that was bound to the port
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
if isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
yield from self._hypervisor.send('ethsw remove_nio "{name}" {nio}'.format(name=self._name, nio=nio))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
del self._nios[port_number]
|
||||
if port_number in self._mappings:
|
||||
del self._mappings[port_number]
|
||||
|
||||
return nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_port_settings(self, port_number, settings):
|
||||
"""
|
||||
Applies port settings to a specific port.
|
||||
|
||||
:param port_number: port number to set the settings
|
||||
:param settings: port settings
|
||||
"""
|
||||
|
||||
if settings["type"] == "access":
|
||||
yield from self.set_access_port(port_number, settings["vlan"])
|
||||
elif settings["type"] == "dot1q":
|
||||
yield from self.set_dot1q_port(port_number, settings["vlan"])
|
||||
elif settings["type"] == "qinq":
|
||||
yield from self.set_qinq_port(port_number, settings["vlan"], settings["ethertype"])
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_access_port(self, port_number, vlan_id):
|
||||
"""
|
||||
Sets the specified port as an ACCESS port.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param vlan_id: VLAN number membership
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
yield from self._hypervisor.send('ethsw set_access_port "{name}" {nio} {vlan_id}'.format(name=self._name,
|
||||
nio=nio,
|
||||
vlan_id=vlan_id))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: port {port} set as an access port in VLAN {vlan_id}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number,
|
||||
vlan_id=vlan_id))
|
||||
self._mappings[port_number] = ("access", vlan_id)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_dot1q_port(self, port_number, native_vlan):
|
||||
"""
|
||||
Sets the specified port as a 802.1Q trunk port.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param native_vlan: native VLAN for this trunk port
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
yield from self._hypervisor.send('ethsw set_dot1q_port "{name}" {nio} {native_vlan}'.format(name=self._name,
|
||||
nio=nio,
|
||||
native_vlan=native_vlan))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: port {port} set as a 802.1Q port with native VLAN {vlan_id}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number,
|
||||
vlan_id=native_vlan))
|
||||
|
||||
self._mappings[port_number] = ("dot1q", native_vlan)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_qinq_port(self, port_number, outer_vlan, ethertype):
|
||||
"""
|
||||
Sets the specified port as a trunk (QinQ) port.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param outer_vlan: outer VLAN (transport VLAN) for this QinQ port
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
if ethertype != "0x8100" and parse_version(self.hypervisor.version) < parse_version('0.2.16'):
|
||||
raise DynamipsError("Dynamips version required is >= 0.2.16 to change the default QinQ Ethernet type, detected version is {}".format(self.hypervisor.version))
|
||||
|
||||
yield from self._hypervisor.send('ethsw set_qinq_port "{name}" {nio} {outer_vlan} {ethertype}'.format(name=self._name,
|
||||
nio=nio,
|
||||
outer_vlan=outer_vlan,
|
||||
ethertype=ethertype if ethertype != "0x8100" else ""))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: port {port} set as a QinQ ({ethertype}) port with outer VLAN {vlan_id}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number,
|
||||
vlan_id=outer_vlan,
|
||||
ethertype=ethertype))
|
||||
self._mappings[port_number] = ("qinq", outer_vlan, ethertype)
|
||||
|
||||
@asyncio.coroutine
|
||||
def get_mac_addr_table(self):
|
||||
"""
|
||||
Returns the MAC address table for this Ethernet switch.
|
||||
|
||||
:returns: list of entries (Ethernet address, VLAN, NIO)
|
||||
"""
|
||||
|
||||
mac_addr_table = yield from self._hypervisor.send('ethsw show_mac_addr_table "{}"'.format(self._name))
|
||||
return mac_addr_table
|
||||
|
||||
@asyncio.coroutine
|
||||
def clear_mac_addr_table(self):
|
||||
"""
|
||||
Clears the MAC address table for this Ethernet switch.
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('ethsw clear_mac_addr_table "{}"'.format(self._name))
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"):
|
||||
"""
|
||||
Starts a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param output_file: PCAP destination file for the capture
|
||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
|
||||
if not nio:
|
||||
raise DynamipsError("Port {} is not connected".format(port_number))
|
||||
|
||||
data_link_type = data_link_type.lower()
|
||||
if data_link_type.startswith("dlt_"):
|
||||
data_link_type = data_link_type[4:]
|
||||
|
||||
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||
raise DynamipsError("Port {} has already a filter applied".format(port_number))
|
||||
|
||||
yield from nio.bind_filter("both", "capture")
|
||||
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
||||
|
||||
log.info('Ethernet switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
|
||||
@asyncio.coroutine
|
||||
def stop_capture(self, port_number):
|
||||
"""
|
||||
Stops a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
|
||||
if not nio:
|
||||
raise DynamipsError("Port {} is not connected".format(port_number))
|
||||
|
||||
yield from nio.unbind_filter("both")
|
||||
log.info('Ethernet switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
@@ -0,0 +1,320 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Interface for Dynamips virtual Frame-Relay switch module.
|
||||
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from .device import Device
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from ..dynamips_error import DynamipsError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FrameRelaySwitch(Device):
|
||||
|
||||
"""
|
||||
Dynamips Frame Relay switch.
|
||||
|
||||
:param name: name for this switch
|
||||
:param device_id: Device instance identifier
|
||||
:param project: Project instance
|
||||
:param manager: Parent VM Manager
|
||||
:param hypervisor: Dynamips hypervisor instance
|
||||
"""
|
||||
|
||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
||||
|
||||
super().__init__(name, device_id, project, manager, hypervisor)
|
||||
self._nios = {}
|
||||
self._mappings = {}
|
||||
|
||||
def __json__(self):
|
||||
|
||||
mappings = {}
|
||||
for source, destination in self._mappings.items():
|
||||
mappings[str(source)] = str(destination)
|
||||
|
||||
return {"name": self.name,
|
||||
"device_id": self.id,
|
||||
"project_id": self.project.id,
|
||||
"mappings": mappings}
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
|
||||
if self._hypervisor is None:
|
||||
module_workdir = self.project.module_working_directory(self.manager.module_name.lower())
|
||||
self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir)
|
||||
|
||||
yield from self._hypervisor.send('frsw create "{}"'.format(self._name))
|
||||
log.info('Frame Relay switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||
self._hypervisor.devices.append(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_name(self, new_name):
|
||||
"""
|
||||
Renames this Frame Relay switch.
|
||||
|
||||
:param new_name: New name for this switch
|
||||
"""
|
||||
|
||||
yield from self._hypervisor.send('frsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name))
|
||||
log.info('Frame Relay switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name,
|
||||
id=self._id,
|
||||
new_name=new_name))
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def nios(self):
|
||||
"""
|
||||
Returns all the NIOs member of this Frame Relay switch.
|
||||
|
||||
:returns: nio list
|
||||
"""
|
||||
|
||||
return self._nios
|
||||
|
||||
@property
|
||||
def mappings(self):
|
||||
"""
|
||||
Returns port mappings
|
||||
|
||||
:returns: mappings list
|
||||
"""
|
||||
|
||||
return self._mappings
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this Frame Relay switch.
|
||||
"""
|
||||
|
||||
for nio in self._nios.values():
|
||||
if nio and isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
try:
|
||||
yield from self._hypervisor.send('frsw delete "{}"'.format(self._name))
|
||||
log.info('Frame Relay switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id))
|
||||
except DynamipsError:
|
||||
log.debug("Could not properly delete Frame relay switch {}".format(self._name))
|
||||
if self._hypervisor and self in self._hypervisor.devices:
|
||||
self._hypervisor.devices.remove(self)
|
||||
if self._hypervisor and not self._hypervisor.devices:
|
||||
yield from self.hypervisor.stop()
|
||||
|
||||
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_number):
|
||||
"""
|
||||
Adds a NIO as new port on Frame Relay switch.
|
||||
|
||||
:param nio: NIO instance to add
|
||||
:param port_number: port to allocate for the NIO
|
||||
"""
|
||||
|
||||
if port_number in self._nios:
|
||||
raise DynamipsError("Port {} isn't free".format(port_number))
|
||||
|
||||
log.info('Frame Relay switch "{name}" [{id}]: NIO {nio} bound to port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
self._nios[port_number] = nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_nio(self, port_number):
|
||||
"""
|
||||
Removes the specified NIO as member of this Frame Relay switch.
|
||||
|
||||
:param port_number: allocated port number
|
||||
|
||||
:returns: the NIO that was bound to the allocated port
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
# remove VCs mapped with the port
|
||||
for source, destination in self._mappings.copy().items():
|
||||
source_port, source_dlci = source
|
||||
destination_port, destination_dlci = destination
|
||||
if port_number == source_port:
|
||||
yield from self.unmap_vc(source_port, source_dlci, destination_port, destination_dlci)
|
||||
yield from self.unmap_vc(destination_port, destination_dlci, source_port, source_dlci)
|
||||
|
||||
nio = self._nios[port_number]
|
||||
if isinstance(nio, NIOUDP):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
log.info('Frame Relay switch "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
nio=nio,
|
||||
port=port_number))
|
||||
|
||||
del self._nios[port_number]
|
||||
return nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_mappings(self, mappings):
|
||||
"""
|
||||
Applies VC mappings
|
||||
|
||||
:param mappings: mappings (dict)
|
||||
"""
|
||||
|
||||
for source, destination in mappings.items():
|
||||
if not isinstance(source, str) or not isinstance(destination, str):
|
||||
raise DynamipsError("Invalid Frame-Relay mappings")
|
||||
source_port, source_dlci = map(int, source.split(':'))
|
||||
destination_port, destination_dlci = map(int, destination.split(':'))
|
||||
if self.has_port(destination_port):
|
||||
if (source_port, source_dlci) not in self.mappings and (destination_port, destination_dlci) not in self.mappings:
|
||||
yield from self.map_vc(source_port, source_dlci, destination_port, destination_dlci)
|
||||
yield from self.map_vc(destination_port, destination_dlci, source_port, source_dlci)
|
||||
|
||||
@asyncio.coroutine
|
||||
def map_vc(self, port1, dlci1, port2, dlci2):
|
||||
"""
|
||||
Creates a new Virtual Circuit connection (unidirectional).
|
||||
|
||||
:param port1: input port
|
||||
:param dlci1: input DLCI
|
||||
:param port2: output port
|
||||
:param dlci2: output DLCI
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('frsw create_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_dlci=dlci1,
|
||||
output_nio=nio2,
|
||||
output_dlci=dlci2))
|
||||
|
||||
log.info('Frame Relay switch "{name}" [{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._mappings[(port1, dlci1)] = (port2, dlci2)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unmap_vc(self, port1, dlci1, port2, dlci2):
|
||||
"""
|
||||
Deletes a Virtual Circuit connection (unidirectional).
|
||||
|
||||
:param port1: input port
|
||||
:param dlci1: input DLCI
|
||||
:param port2: output port
|
||||
:param dlci2: output DLCI
|
||||
"""
|
||||
|
||||
if port1 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port1))
|
||||
|
||||
if port2 not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port2))
|
||||
|
||||
nio1 = self._nios[port1]
|
||||
nio2 = self._nios[port2]
|
||||
|
||||
yield from self._hypervisor.send('frsw delete_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name,
|
||||
input_nio=nio1,
|
||||
input_dlci=dlci1,
|
||||
output_nio=nio2,
|
||||
output_dlci=dlci2))
|
||||
|
||||
log.info('Frame Relay switch "{name}" [{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._mappings[(port1, dlci1)]
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_capture(self, port_number, output_file, data_link_type="DLT_FRELAY"):
|
||||
"""
|
||||
Starts a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
:param output_file: PCAP destination file for the capture
|
||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_FRELAY
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
|
||||
data_link_type = data_link_type.lower()
|
||||
if data_link_type.startswith("dlt_"):
|
||||
data_link_type = data_link_type[4:]
|
||||
|
||||
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||
raise DynamipsError("Port {} has already a filter applied".format(port_number))
|
||||
|
||||
yield from nio.bind_filter("both", "capture")
|
||||
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
||||
|
||||
log.info('Frame relay switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
|
||||
@asyncio.coroutine
|
||||
def stop_capture(self, port_number):
|
||||
"""
|
||||
Stops a packet capture.
|
||||
|
||||
:param port_number: allocated port number
|
||||
"""
|
||||
|
||||
if port_number not in self._nios:
|
||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||
|
||||
nio = self._nios[port_number]
|
||||
yield from nio.unbind_filter("both")
|
||||
log.info('Frame relay switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||
id=self._id,
|
||||
port=port_number))
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user