mirror of
https://github.com/GNS3/gns3-server
synced 2025-07-09 16:18:29 +00:00
Dynamips NIO connections.
This commit is contained in:
parent
83edc649d2
commit
a5ac7c5481
@ -20,6 +20,7 @@ import asyncio
|
|||||||
from ..web.route import Route
|
from ..web.route import Route
|
||||||
from ..schemas.dynamips import VM_CREATE_SCHEMA
|
from ..schemas.dynamips import VM_CREATE_SCHEMA
|
||||||
from ..schemas.dynamips import VM_UPDATE_SCHEMA
|
from ..schemas.dynamips import VM_UPDATE_SCHEMA
|
||||||
|
from ..schemas.dynamips import VM_NIO_SCHEMA
|
||||||
from ..schemas.dynamips import VM_OBJECT_SCHEMA
|
from ..schemas.dynamips import VM_OBJECT_SCHEMA
|
||||||
from ..modules.dynamips import Dynamips
|
from ..modules.dynamips import Dynamips
|
||||||
from ..modules.project_manager import ProjectManager
|
from ..modules.project_manager import ProjectManager
|
||||||
@ -238,3 +239,54 @@ class DynamipsHandler:
|
|||||||
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
yield from vm.reload()
|
yield from vm.reload()
|
||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
|
||||||
|
@Route.post(
|
||||||
|
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
|
||||||
|
parameters={
|
||||||
|
"project_id": "UUID for the project",
|
||||||
|
"vm_id": "UUID for the instance",
|
||||||
|
"adapter_number": "Adapter where the nio should be added",
|
||||||
|
"port_number": "Port on the adapter"
|
||||||
|
},
|
||||||
|
status_codes={
|
||||||
|
201: "NIO created",
|
||||||
|
400: "Invalid request",
|
||||||
|
404: "Instance doesn't exist"
|
||||||
|
},
|
||||||
|
description="Add a NIO to a Dynamips VM instance",
|
||||||
|
input=VM_NIO_SCHEMA,
|
||||||
|
output=VM_NIO_SCHEMA)
|
||||||
|
def create_nio(request, response):
|
||||||
|
|
||||||
|
dynamips_manager = Dynamips.instance()
|
||||||
|
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
|
nio = yield from dynamips_manager.create_nio(vm, request.json)
|
||||||
|
slot_number = int(request.match_info["adapter_number"])
|
||||||
|
port_number = int(request.match_info["port_number"])
|
||||||
|
yield from vm.slot_add_nio_binding(slot_number, port_number, nio)
|
||||||
|
response.set_status(201)
|
||||||
|
response.json(nio)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@Route.delete(
|
||||||
|
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
|
||||||
|
parameters={
|
||||||
|
"project_id": "UUID for the project",
|
||||||
|
"vm_id": "UUID for the instance",
|
||||||
|
"adapter_number": "Adapter from where the nio should be removed",
|
||||||
|
"port_number": "Port on the adapter"
|
||||||
|
},
|
||||||
|
status_codes={
|
||||||
|
204: "NIO deleted",
|
||||||
|
400: "Invalid request",
|
||||||
|
404: "Instance doesn't exist"
|
||||||
|
},
|
||||||
|
description="Remove a NIO from a Dynamips VM instance")
|
||||||
|
def delete_nio(request, response):
|
||||||
|
|
||||||
|
dynamips_manager = Dynamips.instance()
|
||||||
|
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
|
slot_number = int(request.match_info["adapter_number"])
|
||||||
|
port_number = int(request.match_info["port_number"])
|
||||||
|
yield from vm.slot_remove_nio_binding(slot_number, port_number)
|
||||||
|
response.set_status(204)
|
||||||
|
@ -252,12 +252,12 @@ class VirtualBoxHandler:
|
|||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
|
||||||
@Route.post(
|
@Route.post(
|
||||||
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/ports/{port_id:\d+}/nio",
|
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
|
||||||
parameters={
|
parameters={
|
||||||
"project_id": "UUID for the project",
|
"project_id": "UUID for the project",
|
||||||
"vm_id": "UUID for the instance",
|
"vm_id": "UUID for the instance",
|
||||||
"adapter_id": "Adapter where the nio should be added",
|
"adapter_number": "Adapter where the nio should be added",
|
||||||
"port_id": "Port in the adapter (always 0 for virtualbox)"
|
"port_number": "Port on the adapter (always 0)"
|
||||||
},
|
},
|
||||||
status_codes={
|
status_codes={
|
||||||
201: "NIO created",
|
201: "NIO created",
|
||||||
@ -272,18 +272,18 @@ class VirtualBoxHandler:
|
|||||||
vbox_manager = VirtualBox.instance()
|
vbox_manager = VirtualBox.instance()
|
||||||
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
nio = vbox_manager.create_nio(vbox_manager.vboxmanage_path, request.json)
|
nio = vbox_manager.create_nio(vbox_manager.vboxmanage_path, request.json)
|
||||||
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_id"]), nio)
|
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
|
||||||
response.set_status(201)
|
response.set_status(201)
|
||||||
response.json(nio)
|
response.json(nio)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@Route.delete(
|
@Route.delete(
|
||||||
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/ports/{port_id:\d+}/nio",
|
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
|
||||||
parameters={
|
parameters={
|
||||||
"project_id": "UUID for the project",
|
"project_id": "UUID for the project",
|
||||||
"vm_id": "UUID for the instance",
|
"vm_id": "UUID for the instance",
|
||||||
"adapter_id": "Adapter from where the nio should be removed",
|
"adapter_number": "Adapter from where the nio should be removed",
|
||||||
"port_id": "Port in the adapter (always 0 for virtualbox)"
|
"port_number": "Port on the adapter (always)"
|
||||||
},
|
},
|
||||||
status_codes={
|
status_codes={
|
||||||
204: "NIO deleted",
|
204: "NIO deleted",
|
||||||
@ -295,15 +295,16 @@ class VirtualBoxHandler:
|
|||||||
|
|
||||||
vbox_manager = VirtualBox.instance()
|
vbox_manager = VirtualBox.instance()
|
||||||
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_id"]))
|
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
|
||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
|
||||||
@Route.post(
|
@Route.post(
|
||||||
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/start_capture",
|
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
|
||||||
parameters={
|
parameters={
|
||||||
"project_id": "UUID for the project",
|
"project_id": "UUID for the project",
|
||||||
"vm_id": "UUID for the instance",
|
"vm_id": "UUID for the instance",
|
||||||
"adapter_id": "Adapter to start a packet capture"
|
"adapter_number": "Adapter to start a packet capture",
|
||||||
|
"port_number": "Port on the adapter (always 0)"
|
||||||
},
|
},
|
||||||
status_codes={
|
status_codes={
|
||||||
200: "Capture started",
|
200: "Capture started",
|
||||||
@ -316,17 +317,18 @@ class VirtualBoxHandler:
|
|||||||
|
|
||||||
vbox_manager = VirtualBox.instance()
|
vbox_manager = VirtualBox.instance()
|
||||||
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
adapter_id = int(request.match_info["adapter_id"])
|
adapter_number = int(request.match_info["adapter_number"])
|
||||||
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
|
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
|
||||||
vm.start_capture(adapter_id, pcap_file_path)
|
vm.start_capture(adapter_number, pcap_file_path)
|
||||||
response.json({"pcap_file_path": pcap_file_path})
|
response.json({"pcap_file_path": pcap_file_path})
|
||||||
|
|
||||||
@Route.post(
|
@Route.post(
|
||||||
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/stop_capture",
|
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
|
||||||
parameters={
|
parameters={
|
||||||
"project_id": "UUID for the project",
|
"project_id": "UUID for the project",
|
||||||
"vm_id": "UUID for the instance",
|
"vm_id": "UUID for the instance",
|
||||||
"adapter_id": "Adapter to stop a packet capture"
|
"adapter_number": "Adapter to stop a packet capture",
|
||||||
|
"port_number": "Port on the adapter (always 0)"
|
||||||
},
|
},
|
||||||
status_codes={
|
status_codes={
|
||||||
204: "Capture stopped",
|
204: "Capture stopped",
|
||||||
@ -338,5 +340,5 @@ class VirtualBoxHandler:
|
|||||||
|
|
||||||
vbox_manager = VirtualBox.instance()
|
vbox_manager = VirtualBox.instance()
|
||||||
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
vm.stop_capture(int(request.match_info["adapter_id"]))
|
vm.stop_capture(int(request.match_info["adapter_number"]))
|
||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
@ -21,7 +21,7 @@ from .adapter import Adapter
|
|||||||
class EthernetAdapter(Adapter):
|
class EthernetAdapter(Adapter):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
VPCS Ethernet adapter.
|
Ethernet adapter.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interfaces=1):
|
def __init__(self, interfaces=1):
|
||||||
|
@ -21,7 +21,7 @@ from .adapter import Adapter
|
|||||||
class SerialAdapter(Adapter):
|
class SerialAdapter(Adapter):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
VPCS Ethernet adapter.
|
Ethernet adapter.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interfaces=1):
|
def __init__(self, interfaces=1):
|
||||||
|
@ -170,35 +170,7 @@ class Dynamips(BaseManager):
|
|||||||
|
|
||||||
return hypervisor
|
return hypervisor
|
||||||
|
|
||||||
def create_nio(self, executable, nio_settings):
|
@asyncio.coroutine
|
||||||
"""
|
|
||||||
Creates a new NIO.
|
|
||||||
|
|
||||||
:param nio_settings: information to create the NIO
|
|
||||||
|
|
||||||
:returns: a NIO object
|
|
||||||
"""
|
|
||||||
|
|
||||||
nio = None
|
|
||||||
if nio_settings["type"] == "nio_udp":
|
|
||||||
lport = nio_settings["lport"]
|
|
||||||
rhost = nio_settings["rhost"]
|
|
||||||
rport = nio_settings["rport"]
|
|
||||||
try:
|
|
||||||
# TODO: handle IPv6
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
|
||||||
sock.connect((rhost, rport))
|
|
||||||
except OSError as e:
|
|
||||||
raise aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
|
||||||
nio = NIOUDP(lport, rhost, rport)
|
|
||||||
elif nio_settings["type"] == "nio_tap":
|
|
||||||
tap_device = nio_settings["tap_device"]
|
|
||||||
if not self._has_privileged_access(executable):
|
|
||||||
raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, tap_device))
|
|
||||||
nio = NIOTAP(tap_device)
|
|
||||||
assert nio is not None
|
|
||||||
return nio
|
|
||||||
|
|
||||||
def create_nio(self, node, nio_settings):
|
def create_nio(self, node, nio_settings):
|
||||||
"""
|
"""
|
||||||
Creates a new NIO.
|
Creates a new NIO.
|
||||||
@ -221,12 +193,12 @@ class Dynamips(BaseManager):
|
|||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
|
||||||
# check if we have an allocated NIO UDP auto
|
# check if we have an allocated NIO UDP auto
|
||||||
nio = node.hypervisor.get_nio_udp_auto(lport)
|
#nio = node.hypervisor.get_nio_udp_auto(lport)
|
||||||
if not nio:
|
#if not nio:
|
||||||
# otherwise create an NIO UDP
|
# otherwise create an NIO UDP
|
||||||
nio = NIOUDP(node.hypervisor, lport, rhost, rport)
|
nio = NIOUDP(node.hypervisor, lport, rhost, rport)
|
||||||
else:
|
#else:
|
||||||
nio.connect(rhost, rport)
|
# nio.connect(rhost, rport)
|
||||||
elif nio_settings["type"] == "nio_generic_ethernet":
|
elif nio_settings["type"] == "nio_generic_ethernet":
|
||||||
ethernet_device = nio_settings["ethernet_device"]
|
ethernet_device = nio_settings["ethernet_device"]
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
@ -259,6 +231,8 @@ class Dynamips(BaseManager):
|
|||||||
nio = NIOVDE(node.hypervisor, control_file, local_file)
|
nio = NIOVDE(node.hypervisor, control_file, local_file)
|
||||||
elif nio_settings["type"] == "nio_null":
|
elif nio_settings["type"] == "nio_null":
|
||||||
nio = NIONull(node.hypervisor)
|
nio = NIONull(node.hypervisor)
|
||||||
|
|
||||||
|
yield from nio.create()
|
||||||
return nio
|
return nio
|
||||||
|
|
||||||
# def set_ghost_ios(self, router):
|
# def set_ghost_ios(self, router):
|
||||||
|
@ -38,7 +38,7 @@ class NIO:
|
|||||||
def __init__(self, name, hypervisor):
|
def __init__(self, name, hypervisor):
|
||||||
|
|
||||||
self._hypervisor = hypervisor
|
self._hypervisor = hypervisor
|
||||||
self._name = None
|
self._name = name
|
||||||
self._bandwidth = None # no bandwidth constraint by default
|
self._bandwidth = None # no bandwidth constraint by default
|
||||||
self._input_filter = None # no input filter applied by default
|
self._input_filter = None # no input filter applied by default
|
||||||
self._output_filter = None # no output filter applied by default
|
self._output_filter = None # no output filter applied by default
|
||||||
|
@ -38,12 +38,11 @@ class NIOFIFO(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor):
|
def __init__(self, hypervisor):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOFIFO._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOFIFO._instance_count
|
|
||||||
NIOFIFO._instance_count += 1
|
NIOFIFO._instance_count += 1
|
||||||
self._name = 'nio_fifo' + str(self._id)
|
name = 'nio_fifo' + str(nio_id)
|
||||||
|
NIO.__init__(name, self, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -71,3 +70,7 @@ class NIOFIFO(NIO):
|
|||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
log.info("NIO FIFO {name} crossconnected with {nio_name}.".format(name=self._name, nio_name=nio.name))
|
log.info("NIO FIFO {name} crossconnected with {nio_name}.".format(name=self._name, nio_name=nio.name))
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_fifo"}
|
||||||
|
@ -39,13 +39,12 @@ class NIOGenericEthernet(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, ethernet_device):
|
def __init__(self, hypervisor, ethernet_device):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOGenericEthernet._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOGenericEthernet._instance_count
|
|
||||||
NIOGenericEthernet._instance_count += 1
|
NIOGenericEthernet._instance_count += 1
|
||||||
self._name = 'nio_gen_eth' + str(self._id)
|
name = 'nio_gen_eth' + str(nio_id)
|
||||||
self._ethernet_device = ethernet_device
|
self._ethernet_device = ethernet_device
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -73,3 +72,8 @@ class NIOGenericEthernet(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._ethernet_device
|
return self._ethernet_device
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_generic_ethernet",
|
||||||
|
"ethernet_device": self._ethernet_device}
|
||||||
|
@ -39,13 +39,12 @@ class NIOLinuxEthernet(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, ethernet_device):
|
def __init__(self, hypervisor, ethernet_device):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOLinuxEthernet._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOLinuxEthernet._instance_count
|
|
||||||
NIOLinuxEthernet._instance_count += 1
|
NIOLinuxEthernet._instance_count += 1
|
||||||
self._name = 'nio_linux_eth' + str(self._id)
|
name = 'nio_linux_eth' + str(nio_id)
|
||||||
self._ethernet_device = ethernet_device
|
self._ethernet_device = ethernet_device
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -73,3 +72,8 @@ class NIOLinuxEthernet(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._ethernet_device
|
return self._ethernet_device
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_linux_ethernet",
|
||||||
|
"ethernet_device": self._ethernet_device}
|
||||||
|
@ -40,15 +40,14 @@ class NIOMcast(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, group, port):
|
def __init__(self, hypervisor, group, port):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOMcast._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOMcast._instance_count
|
|
||||||
NIOMcast._instance_count += 1
|
NIOMcast._instance_count += 1
|
||||||
self._name = 'nio_mcast' + str(self._id)
|
name = 'nio_mcast' + str(nio_id)
|
||||||
self._group = group
|
self._group = group
|
||||||
self._port = port
|
self._port = port
|
||||||
self._ttl = 1 # default TTL
|
self._ttl = 1 # default TTL
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -109,3 +108,9 @@ class NIOMcast(NIO):
|
|||||||
yield from self._hypervisor.send("nio set_mcast_ttl {name} {ttl}".format(name=self._name,
|
yield from self._hypervisor.send("nio set_mcast_ttl {name} {ttl}".format(name=self._name,
|
||||||
ttl=ttl))
|
ttl=ttl))
|
||||||
self._ttl = ttl
|
self._ttl = ttl
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_mcast",
|
||||||
|
"mgroup": self._mgroup,
|
||||||
|
"mport": self._mport}
|
||||||
|
@ -38,12 +38,11 @@ class NIONull(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor):
|
def __init__(self, hypervisor):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIONull._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIONull._instance_count
|
|
||||||
NIONull._instance_count += 1
|
NIONull._instance_count += 1
|
||||||
self._name = 'nio_null' + str(self._id)
|
name = 'nio_null' + str(nio_id)
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -58,3 +57,7 @@ class NIONull(NIO):
|
|||||||
|
|
||||||
yield from self._hypervisor.send("nio create_null {}".format(self._name))
|
yield from self._hypervisor.send("nio create_null {}".format(self._name))
|
||||||
log.info("NIO NULL {name} created.".format(name=self._name))
|
log.info("NIO NULL {name} created.".format(name=self._name))
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_null"}
|
||||||
|
@ -39,13 +39,12 @@ class NIOTAP(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, tap_device):
|
def __init__(self, hypervisor, tap_device):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOTAP._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOTAP._instance_count
|
|
||||||
NIOTAP._instance_count += 1
|
NIOTAP._instance_count += 1
|
||||||
self._name = 'nio_tap' + str(self._id)
|
name = 'nio_tap' + str(nio_id)
|
||||||
self._tap_device = tap_device
|
self._tap_device = tap_device
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -70,3 +69,8 @@ class NIOTAP(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._tap_device
|
return self._tap_device
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_tap",
|
||||||
|
"tap_device": self._tap_device}
|
||||||
|
@ -41,15 +41,14 @@ class NIOUDP(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, lport, rhost, rport):
|
def __init__(self, hypervisor, lport, rhost, rport):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOUDP._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOUDP._instance_count
|
|
||||||
NIOUDP._instance_count += 1
|
NIOUDP._instance_count += 1
|
||||||
self._name = 'nio_udp' + str(self._id)
|
name = 'nio_udp' + str(nio_id)
|
||||||
self._lport = lport
|
self._lport = lport
|
||||||
self._rhost = rhost
|
self._rhost = rhost
|
||||||
self._rport = rport
|
self._rport = rport
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -101,3 +100,10 @@ class NIOUDP(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._rport
|
return self._rport
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_udp",
|
||||||
|
"lport": self._lport,
|
||||||
|
"rport": self._rport,
|
||||||
|
"rhost": self._rhost}
|
||||||
|
@ -41,17 +41,15 @@ class NIOUDPAuto(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, laddr, lport_start, lport_end):
|
def __init__(self, hypervisor, laddr, lport_start, lport_end):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOUDPAuto._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOUDPAuto._instance_count
|
|
||||||
NIOUDPAuto._instance_count += 1
|
NIOUDPAuto._instance_count += 1
|
||||||
self._name = 'nio_udp_auto' + str(self._id)
|
name = 'nio_udp_auto' + str(nio_id)
|
||||||
|
|
||||||
self._laddr = laddr
|
self._laddr = laddr
|
||||||
self._lport = None
|
self._lport = None
|
||||||
self._raddr = None
|
self._raddr = None
|
||||||
self._rport = None
|
self._rport = None
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -133,3 +131,10 @@ class NIOUDPAuto(NIO):
|
|||||||
log.info("NIO UDP AUTO {name} connected to {raddr}:{rport}".format(name=self._name,
|
log.info("NIO UDP AUTO {name} connected to {raddr}:{rport}".format(name=self._name,
|
||||||
raddr=raddr,
|
raddr=raddr,
|
||||||
rport=rport))
|
rport=rport))
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_udp_auto",
|
||||||
|
"lport": self._lport,
|
||||||
|
"rport": self._rport,
|
||||||
|
"raddr": self._raddr}
|
||||||
|
@ -40,14 +40,13 @@ class NIOUNIX(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, local_file, remote_file):
|
def __init__(self, hypervisor, local_file, remote_file):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOUNIX._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOUNIX._instance_count
|
|
||||||
NIOUNIX._instance_count += 1
|
NIOUNIX._instance_count += 1
|
||||||
self._name = 'nio_unix' + str(self._id)
|
name = 'nio_unix' + str(nio_id)
|
||||||
self._local_file = local_file
|
self._local_file = local_file
|
||||||
self._remote_file = remote_file
|
self._remote_file = remote_file
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -87,3 +86,9 @@ class NIOUNIX(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._remote_file
|
return self._remote_file
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_unix",
|
||||||
|
"local_file": self._local_file,
|
||||||
|
"remote_file": self._remote_file}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
Interface for VDE (Virtual Distributed Ethernet) NIOs (Unix based OSes only).
|
Interface for VDE (Virtual Distributed Ethernet) NIOs (Unix based OSes only).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
from .nio import NIO
|
from .nio import NIO
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -39,22 +40,13 @@ class NIOVDE(NIO):
|
|||||||
|
|
||||||
def __init__(self, hypervisor, control_file, local_file):
|
def __init__(self, hypervisor, control_file, local_file):
|
||||||
|
|
||||||
NIO.__init__(self, hypervisor)
|
# create an unique ID and name
|
||||||
|
nio_id = NIOVDE._instance_count
|
||||||
# create an unique ID
|
|
||||||
self._id = NIOVDE._instance_count
|
|
||||||
NIOVDE._instance_count += 1
|
NIOVDE._instance_count += 1
|
||||||
self._name = 'nio_vde' + str(self._id)
|
name = 'nio_vde' + str(nio_id)
|
||||||
self._control_file = control_file
|
self._control_file = control_file
|
||||||
self._local_file = local_file
|
self._local_file = local_file
|
||||||
|
NIO.__init__(self, name, hypervisor)
|
||||||
self._hypervisor.send("nio create_vde {name} {control} {local}".format(name=self._name,
|
|
||||||
control=control_file,
|
|
||||||
local=local_file))
|
|
||||||
|
|
||||||
log.info("NIO VDE {name} created with control={control}, local={local}".format(name=self._name,
|
|
||||||
control=control_file,
|
|
||||||
local=local_file))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
@ -64,6 +56,17 @@ class NIOVDE(NIO):
|
|||||||
|
|
||||||
cls._instance_count = 0
|
cls._instance_count = 0
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def create(self):
|
||||||
|
|
||||||
|
self._hypervisor.send("nio create_vde {name} {control} {local}".format(name=self._name,
|
||||||
|
control=self._control_file,
|
||||||
|
local=self._local_file))
|
||||||
|
|
||||||
|
log.info("NIO VDE {name} created with control={control}, local={local}".format(name=self._name,
|
||||||
|
control=self._control_file,
|
||||||
|
local=self._local_file))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def control_file(self):
|
def control_file(self):
|
||||||
"""
|
"""
|
||||||
@ -83,3 +86,9 @@ class NIOVDE(NIO):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return self._local_file
|
return self._local_file
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_vde",
|
||||||
|
"local_file": self._local_file,
|
||||||
|
"control_file": self._control_file}
|
||||||
|
@ -145,16 +145,16 @@ class Router(BaseVM):
|
|||||||
"system_id": self._system_id}
|
"system_id": self._system_id}
|
||||||
|
|
||||||
# FIXME: add default slots/wics
|
# FIXME: add default slots/wics
|
||||||
# slot_id = 0
|
# slot_number = 0
|
||||||
# for slot in self._slots:
|
# for slot in self._slots:
|
||||||
# if slot:
|
# if slot:
|
||||||
# slot = str(slot)
|
# slot = str(slot)
|
||||||
# router_defaults["slot" + str(slot_id)] = slot
|
# router_defaults["slot" + str(slot_number)] = slot
|
||||||
# slot_id += 1
|
# slot_number += 1
|
||||||
|
|
||||||
# if self._slots[0] and self._slots[0].wics:
|
# if self._slots[0] and self._slots[0].wics:
|
||||||
# for wic_slot_id in range(0, len(self._slots[0].wics)):
|
# for wic_slot_number in range(0, len(self._slots[0].wics)):
|
||||||
# router_defaults["wic" + str(wic_slot_id)] = None
|
# router_defaults["wic" + str(wic_slot_number)] = None
|
||||||
|
|
||||||
return router_info
|
return router_info
|
||||||
|
|
||||||
@ -991,23 +991,23 @@ class Router(BaseVM):
|
|||||||
return slot_bindings
|
return slot_bindings
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_add_binding(self, slot_id, adapter):
|
def slot_add_binding(self, slot_number, adapter):
|
||||||
"""
|
"""
|
||||||
Adds a slot binding (a module into a slot).
|
Adds a slot binding (a module into a slot).
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param adapter: device to add in the corresponding slot
|
:param adapter: device to add in the corresponding slot
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
slot = self._slots[slot_id]
|
slot = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name, slot_id=slot_id))
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number))
|
||||||
|
|
||||||
if slot is not None:
|
if slot is not None:
|
||||||
current_adapter = slot
|
current_adapter = slot
|
||||||
raise DynamipsError('Slot {slot_id} is already occupied by adapter {adapter} on router "{name}"'.format(name=self._name,
|
raise DynamipsError('Slot {slot_number} is already occupied by adapter {adapter} on router "{name}"'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
adapter=current_adapter))
|
adapter=current_adapter))
|
||||||
|
|
||||||
is_running = yield from self.is_running()
|
is_running = yield from self.is_running()
|
||||||
@ -1019,42 +1019,44 @@ class Router(BaseVM):
|
|||||||
raise DynamipsError('Adapter {adapter} cannot be added while router "{name}" is running'.format(adapter=adapter,
|
raise DynamipsError('Adapter {adapter} cannot be added while router "{name}" is running'.format(adapter=adapter,
|
||||||
name=self._name))
|
name=self._name))
|
||||||
|
|
||||||
yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_id} 0 {adapter}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} 0 {adapter}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
adapter=adapter))
|
adapter=adapter))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: adapter {adapter} inserted into slot {slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: adapter {adapter} inserted into slot {slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapter=adapter,
|
adapter=adapter,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
|
|
||||||
self._slots[slot_id] = adapter
|
self._slots[slot_number] = adapter
|
||||||
|
|
||||||
# Generate an OIR event if the router is running
|
# Generate an OIR event if the router is running
|
||||||
if is_running:
|
if is_running:
|
||||||
|
|
||||||
yield from self._hypervisor.send('vm slot_oir_start "{name}" {slot_id} 0'.format(name=self._name, slot_id=slot_id))
|
yield from self._hypervisor.send('vm slot_oir_start "{name}" {slot_number} 0'.format(name=self._name,
|
||||||
|
slot_number=slot_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: OIR start event sent to slot {slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: OIR start event sent to slot {slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_remove_binding(self, slot_id):
|
def slot_remove_binding(self, slot_number):
|
||||||
"""
|
"""
|
||||||
Removes a slot binding (a module from a slot).
|
Removes a slot binding (a module from a slot).
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name, slot_id=slot_id))
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name,
|
||||||
|
slot_number=slot_number))
|
||||||
|
|
||||||
if adapter is None:
|
if adapter is None:
|
||||||
raise DynamipsError('No adapter in slot {slot_id} on router "{name}"'.format(name=self._name,
|
raise DynamipsError('No adapter in slot {slot_number} on router "{name}"'.format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
|
|
||||||
is_running = yield from self.is_running()
|
is_running = yield from self.is_running()
|
||||||
|
|
||||||
@ -1068,239 +1070,245 @@ class Router(BaseVM):
|
|||||||
# Generate an OIR event if the router is running
|
# Generate an OIR event if the router is running
|
||||||
if is_running:
|
if is_running:
|
||||||
|
|
||||||
yield from self._hypervisor.send('vm slot_oir_stop "{name}" {slot_id} 0'.format(name=self._name, slot_id=slot_id))
|
yield from self._hypervisor.send('vm slot_oir_stop "{name}" {slot_number} 0'.format(name=self._name,
|
||||||
|
slot_number=slot_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: OIR stop event sent to slot {slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: OIR stop event sent to slot {slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
|
|
||||||
yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_id} 0'.format(name=self._name, slot_id=slot_id))
|
yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} 0'.format(name=self._name,
|
||||||
|
slot_number=slot_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: adapter {adapter} removed from slot {slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: adapter {adapter} removed from slot {slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapter=adapter,
|
adapter=adapter,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
self._slots[slot_id] = None
|
self._slots[slot_number] = None
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def install_wic(self, wic_slot_id, wic):
|
def install_wic(self, wic_slot_number, wic):
|
||||||
"""
|
"""
|
||||||
Installs a WIC adapter into this router.
|
Installs a WIC adapter into this router.
|
||||||
|
|
||||||
:param wic_slot_id: WIC slot ID
|
:param wic_slot_number: WIC slot number
|
||||||
:param wic: WIC to be installed
|
:param wic: WIC to be installed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# WICs are always installed on adapters in slot 0
|
# WICs are always installed on adapters in slot 0
|
||||||
slot_id = 0
|
slot_number = 0
|
||||||
|
|
||||||
# Do not check if slot has an adapter because adapters with WICs interfaces
|
# Do not check if slot has an adapter because adapters with WICs interfaces
|
||||||
# must be inserted by default in the router and cannot be removed.
|
# must be inserted by default in the router and cannot be removed.
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
|
|
||||||
if wic_slot_id > len(adapter.wics) - 1:
|
if wic_slot_number > len(adapter.wics) - 1:
|
||||||
raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(wic_slot_id=wic_slot_id))
|
raise DynamipsError("WIC slot {wic_slot_number} doesn't exist".format(wic_slot_number=wic_slot_number))
|
||||||
|
|
||||||
if not adapter.wic_slot_available(wic_slot_id):
|
if not adapter.wic_slot_available(wic_slot_number):
|
||||||
raise DynamipsError("WIC slot {wic_slot_id} is already occupied by another WIC".format(wic_slot_id=wic_slot_id))
|
raise DynamipsError("WIC slot {wic_slot_number} is already occupied by another WIC".format(wic_slot_number=wic_slot_number))
|
||||||
|
|
||||||
# Dynamips WICs slot IDs start on a multiple of 16
|
# Dynamips WICs slot IDs start on a multiple of 16
|
||||||
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
||||||
internal_wic_slot_id = 16 * (wic_slot_id + 1)
|
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
||||||
yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_id} {wic_slot_id} {wic}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} {wic_slot_number} {wic}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
wic_slot_id=internal_wic_slot_id,
|
wic_slot_number=internal_wic_slot_number,
|
||||||
wic=wic))
|
wic=wic))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: {wic} inserted into WIC slot {wic_slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: {wic} inserted into WIC slot {wic_slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
wic=wic,
|
wic=wic,
|
||||||
wic_slot_id=wic_slot_id))
|
wic_slot_number=wic_slot_number))
|
||||||
|
|
||||||
adapter.install_wic(wic_slot_id, wic)
|
adapter.install_wic(wic_slot_number, wic)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def uninstall_wic(self, wic_slot_id):
|
def uninstall_wic(self, wic_slot_number):
|
||||||
"""
|
"""
|
||||||
Uninstalls a WIC adapter from this router.
|
Uninstalls a WIC adapter from this router.
|
||||||
|
|
||||||
:param wic_slot_id: WIC slot ID
|
:param wic_slot_number: WIC slot number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# WICs are always installed on adapters in slot 0
|
# WICs are always installed on adapters in slot 0
|
||||||
slot_id = 0
|
slot_number = 0
|
||||||
|
|
||||||
# Do not check if slot has an adapter because adapters with WICs interfaces
|
# Do not check if slot has an adapter because adapters with WICs interfaces
|
||||||
# must be inserted by default in the router and cannot be removed.
|
# must be inserted by default in the router and cannot be removed.
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
|
|
||||||
if wic_slot_id > len(adapter.wics) - 1:
|
if wic_slot_number > len(adapter.wics) - 1:
|
||||||
raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(wic_slot_id=wic_slot_id))
|
raise DynamipsError("WIC slot {wic_slot_number} doesn't exist".format(wic_slot_number=wic_slot_number))
|
||||||
|
|
||||||
if adapter.wic_slot_available(wic_slot_id):
|
if adapter.wic_slot_available(wic_slot_number):
|
||||||
raise DynamipsError("No WIC is installed in WIC slot {wic_slot_id}".format(wic_slot_id=wic_slot_id))
|
raise DynamipsError("No WIC is installed in WIC slot {wic_slot_number}".format(wic_slot_number=wic_slot_number))
|
||||||
|
|
||||||
# Dynamips WICs slot IDs start on a multiple of 16
|
# Dynamips WICs slot IDs start on a multiple of 16
|
||||||
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
||||||
internal_wic_slot_id = 16 * (wic_slot_id + 1)
|
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
||||||
yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_id} {wic_slot_id}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} {wic_slot_number}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
wic_slot_id=internal_wic_slot_id))
|
wic_slot_number=internal_wic_slot_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: {wic} removed from WIC slot {wic_slot_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: {wic} removed from WIC slot {wic_slot_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
wic=adapter.wics[wic_slot_id],
|
wic=adapter.wics[wic_slot_number],
|
||||||
wic_slot_id=wic_slot_id))
|
wic_slot_number=wic_slot_number))
|
||||||
adapter.uninstall_wic(wic_slot_id)
|
adapter.uninstall_wic(wic_slot_number)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def get_slot_nio_bindings(self, slot_id):
|
def get_slot_nio_bindings(self, slot_number):
|
||||||
"""
|
"""
|
||||||
Returns slot NIO bindings.
|
Returns slot NIO bindings.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
|
|
||||||
:returns: list of NIO bindings
|
:returns: list of NIO bindings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
nio_bindings = yield from self._hypervisor.send('vm slot_nio_bindings "{name}" {slot_id}'.format(name=self._name,
|
nio_bindings = yield from self._hypervisor.send('vm slot_nio_bindings "{name}" {slot_number}'.format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
return nio_bindings
|
return nio_bindings
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_add_nio_binding(self, slot_id, port_id, nio):
|
def slot_add_nio_binding(self, slot_number, port_number, nio):
|
||||||
"""
|
"""
|
||||||
Adds a slot NIO binding.
|
Adds a slot NIO binding.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
:param nio: NIO instance to add to the slot/port
|
:param nio: NIO instance to add to the slot/port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name,
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name,
|
||||||
slot_id=slot_id))
|
slot_number=slot_number))
|
||||||
if not adapter.port_exists(port_id):
|
if not adapter.port_exists(port_number):
|
||||||
raise DynamipsError("Port {port_id} does not exist in adapter {adapter}".format(adapter=adapter,
|
raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
yield from self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_id} {port_id} {nio}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id,
|
port_number=port_number,
|
||||||
nio=nio))
|
nio=nio))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: NIO {nio_name} bound to port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: NIO {nio_name} bound to port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio_name=nio.name,
|
nio_name=nio.name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
yield from self.slot_enable_nio(slot_id, port_id)
|
yield from self.slot_enable_nio(slot_number, port_number)
|
||||||
adapter.add_nio(port_id, nio)
|
adapter.add_nio(port_number, nio)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_remove_nio_binding(self, slot_id, port_id):
|
def slot_remove_nio_binding(self, slot_number, port_number):
|
||||||
"""
|
"""
|
||||||
Removes a slot NIO binding.
|
Removes a slot NIO binding.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
|
|
||||||
:returns: removed NIO instance
|
:returns: removed NIO instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name, slot_id=slot_id))
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name,
|
||||||
if not adapter.port_exists(port_id):
|
slot_number=slot_number))
|
||||||
raise DynamipsError("Port {port_id} does not exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
|
if not adapter.port_exists(port_number):
|
||||||
|
raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
|
port_number=port_number))
|
||||||
|
|
||||||
yield from self.slot_disable_nio(slot_id, port_id)
|
yield from self.slot_disable_nio(slot_number, port_number)
|
||||||
yield from self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_id} {port_id}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(port_id)
|
nio = adapter.get_nio(port_number)
|
||||||
adapter.remove_nio(port_id)
|
adapter.remove_nio(port_number)
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: NIO {nio_name} removed from port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: NIO {nio_name} removed from port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio_name=nio.name,
|
nio_name=nio.name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
return nio
|
return nio
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_enable_nio(self, slot_id, port_id):
|
def slot_enable_nio(self, slot_number, port_number):
|
||||||
"""
|
"""
|
||||||
Enables a slot NIO binding.
|
Enables a slot NIO binding.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
is_running = yield from self.is_running()
|
is_running = yield from self.is_running()
|
||||||
if is_running: # running router
|
if is_running: # running router
|
||||||
yield from self._hypervisor.send('vm slot_enable_nio "{name}" {slot_id} {port_id}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_enable_nio "{name}" {slot_number} {port_number}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: NIO enabled on port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: NIO enabled on port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def slot_disable_nio(self, slot_id, port_id):
|
def slot_disable_nio(self, slot_number, port_number):
|
||||||
"""
|
"""
|
||||||
Disables a slot NIO binding.
|
Disables a slot NIO binding.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
is_running = yield from self.is_running()
|
is_running = yield from self.is_running()
|
||||||
if is_running: # running router
|
if is_running: # running router
|
||||||
yield from self._hypervisor.send('vm slot_disable_nio "{name}" {slot_id} {port_id}'.format(name=self._name,
|
yield from self._hypervisor.send('vm slot_disable_nio "{name}" {slot_number} {port_number}'.format(name=self._name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: NIO disabled on port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: NIO disabled on port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def start_capture(self, slot_id, port_id, output_file, data_link_type="DLT_EN10MB"):
|
def start_capture(self, slot_number, port_number, output_file, data_link_type="DLT_EN10MB"):
|
||||||
"""
|
"""
|
||||||
Starts a packet capture.
|
Starts a packet capture.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
:param output_file: PCAP destination file for the capture
|
:param output_file: PCAP destination file for the capture
|
||||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name, slot_id=slot_id))
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name,
|
||||||
if not adapter.port_exists(port_id):
|
slot_number=slot_number))
|
||||||
raise DynamipsError("Port {port_id} does not exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
|
if not adapter.port_exists(port_number):
|
||||||
|
raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
|
port_number=port_number))
|
||||||
|
|
||||||
data_link_type = data_link_type.lower()
|
data_link_type = data_link_type.lower()
|
||||||
if data_link_type.startswith("dlt_"):
|
if data_link_type.startswith("dlt_"):
|
||||||
data_link_type = data_link_type[4:]
|
data_link_type = data_link_type[4:]
|
||||||
|
|
||||||
nio = adapter.get_nio(port_id)
|
nio = adapter.get_nio(port_number)
|
||||||
|
|
||||||
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
||||||
raise DynamipsError("Port {port_id} has already a filter applied on {adapter}".format(adapter=adapter,
|
raise DynamipsError("Port {port_number} has already a filter applied on {adapter}".format(adapter=adapter,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
# FIXME: capture
|
# FIXME: capture
|
||||||
# try:
|
# try:
|
||||||
@ -1311,36 +1319,38 @@ class Router(BaseVM):
|
|||||||
yield from nio.bind_filter("both", "capture")
|
yield from nio.bind_filter("both", "capture")
|
||||||
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: starting packet capture on port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: starting packet capture on port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio_name=nio.name,
|
nio_name=nio.name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop_capture(self, slot_id, port_id):
|
def stop_capture(self, slot_number, port_number):
|
||||||
"""
|
"""
|
||||||
Stops a packet capture.
|
Stops a packet capture.
|
||||||
|
|
||||||
:param slot_id: slot ID
|
:param slot_number: slot number
|
||||||
:param port_id: port ID
|
:param port_number: port number
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._slots[slot_id]
|
adapter = self._slots[slot_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise DynamipsError('Slot {slot_id} does not exist on router "{name}"'.format(name=self._name, slot_id=slot_id))
|
raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name,
|
||||||
if not adapter.port_exists(port_id):
|
slot_number=slot_number))
|
||||||
raise DynamipsError("Port {port_id} does not exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
|
if not adapter.port_exists(port_number):
|
||||||
|
raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
|
port_number=port_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(port_id)
|
nio = adapter.get_nio(port_number)
|
||||||
yield from nio.unbind_filter("both")
|
yield from nio.unbind_filter("both")
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: stopping packet capture on port {slot_id}/{port_id}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: stopping packet capture on port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio_name=nio.name,
|
nio_name=nio.name,
|
||||||
slot_id=slot_id,
|
slot_number=slot_number,
|
||||||
port_id=port_id))
|
port_number=port_number))
|
||||||
|
|
||||||
def _create_slots(self, numslots):
|
def _create_slots(self, numslots):
|
||||||
"""
|
"""
|
||||||
|
@ -46,6 +46,12 @@ VM_CREATE_SCHEMA = {
|
|||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"pattern": "^c[0-9]{4}$"
|
"pattern": "^c[0-9]{4}$"
|
||||||
},
|
},
|
||||||
|
"chassis": {
|
||||||
|
"description": "router chassis model",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"pattern": "^[0-9]{4}(XM)?$"
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"description": "path to the IOS image",
|
"description": "path to the IOS image",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -265,6 +271,12 @@ VM_UPDATE_SCHEMA = {
|
|||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"pattern": "^c[0-9]{4}$"
|
"pattern": "^c[0-9]{4}$"
|
||||||
},
|
},
|
||||||
|
"chassis": {
|
||||||
|
"description": "router chassis model",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"pattern": "^[0-9]{4}(XM)?$"
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"description": "path to the IOS image",
|
"description": "path to the IOS image",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -467,6 +479,147 @@ VM_UPDATE_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VM_NIO_SCHEMA = {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Request validation to add a NIO for a Dynamips VM instance",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"UDP": {
|
||||||
|
"description": "UDP Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_udp"]
|
||||||
|
},
|
||||||
|
"lport": {
|
||||||
|
"description": "Local port",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535
|
||||||
|
},
|
||||||
|
"rhost": {
|
||||||
|
"description": "Remote host",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"rport": {
|
||||||
|
"description": "Remote port",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["type", "lport", "rhost", "rport"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"Ethernet": {
|
||||||
|
"description": "Generic Ethernet Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_generic_ethernet"]
|
||||||
|
},
|
||||||
|
"ethernet_device": {
|
||||||
|
"description": "Ethernet device name e.g. eth0",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "ethernet_device"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"LinuxEthernet": {
|
||||||
|
"description": "Linux Ethernet Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_linux_ethernet"]
|
||||||
|
},
|
||||||
|
"ethernet_device": {
|
||||||
|
"description": "Ethernet device name e.g. eth0",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "ethernet_device"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"TAP": {
|
||||||
|
"description": "TAP Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_tap"]
|
||||||
|
},
|
||||||
|
"tap_device": {
|
||||||
|
"description": "TAP device name e.g. tap0",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "tap_device"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"UNIX": {
|
||||||
|
"description": "UNIX Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_unix"]
|
||||||
|
},
|
||||||
|
"local_file": {
|
||||||
|
"description": "path to the UNIX socket file (local)",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"remote_file": {
|
||||||
|
"description": "path to the UNIX socket file (remote)",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "local_file", "remote_file"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"VDE": {
|
||||||
|
"description": "VDE Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_vde"]
|
||||||
|
},
|
||||||
|
"control_file": {
|
||||||
|
"description": "path to the VDE control file",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"local_file": {
|
||||||
|
"description": "path to the VDE control file",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "control_file", "local_file"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
"NULL": {
|
||||||
|
"description": "NULL Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_null"]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"oneOf": [
|
||||||
|
{"$ref": "#/definitions/UDP"},
|
||||||
|
{"$ref": "#/definitions/Ethernet"},
|
||||||
|
{"$ref": "#/definitions/LinuxEthernet"},
|
||||||
|
{"$ref": "#/definitions/TAP"},
|
||||||
|
{"$ref": "#/definitions/UNIX"},
|
||||||
|
{"$ref": "#/definitions/VDE"},
|
||||||
|
{"$ref": "#/definitions/NULL"},
|
||||||
|
],
|
||||||
|
"additionalProperties": True,
|
||||||
|
"required": ["type"]
|
||||||
|
}
|
||||||
|
|
||||||
VM_OBJECT_SCHEMA = {
|
VM_OBJECT_SCHEMA = {
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
"description": "Dynamips VM instance",
|
"description": "Dynamips VM instance",
|
||||||
@ -501,6 +654,12 @@ VM_OBJECT_SCHEMA = {
|
|||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"pattern": "^c[0-9]{4}$"
|
"pattern": "^c[0-9]{4}$"
|
||||||
},
|
},
|
||||||
|
"chassis": {
|
||||||
|
"description": "router chassis model",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"pattern": "^[0-9]{4}(XM)?$"
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"description": "path to the IOS image",
|
"description": "path to the IOS image",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
Loading…
Reference in New Issue
Block a user