mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 09:18:08 +00:00
Fix remote packet capture and make sure packet capture is stopped when deleting an NIO. Fixes https://github.com/GNS3/gns3-gui/issues/2753
This commit is contained in:
parent
f01706e9e6
commit
4cc5dbc228
@ -441,6 +441,7 @@ class Cloud(BaseNode):
|
|||||||
if port_number not in self._nios:
|
if port_number not in self._nios:
|
||||||
raise NodeError("Port {} is not allocated".format(port_number))
|
raise NodeError("Port {} is not allocated".format(port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
nio = self._nios[port_number]
|
nio = self._nios[port_number]
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
@ -504,6 +505,8 @@ class Cloud(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
bridge_name = "{}-{}".format(self._id, port_number)
|
bridge_name = "{}-{}".format(self._id, port_number)
|
||||||
await self._ubridge_send("bridge stop_capture {name}".format(name=bridge_name))
|
await self._ubridge_send("bridge stop_capture {name}".format(name=bridge_name))
|
||||||
|
@ -942,6 +942,7 @@ class DockerVM(BaseNode):
|
|||||||
raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name,
|
raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
|
await self.stop_capture(adapter_number)
|
||||||
if self.ubridge:
|
if self.ubridge:
|
||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
bridge_name = 'bridge{}'.format(adapter_number)
|
bridge_name = 'bridge{}'.format(adapter_number)
|
||||||
@ -1073,6 +1074,8 @@ class DockerVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(adapter_number)
|
nio = self.get_nio(adapter_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
if self.status == "started" and self.ubridge:
|
if self.status == "started" and self.ubridge:
|
||||||
await self._stop_ubridge_capture(adapter_number)
|
await self._stop_ubridge_capture(adapter_number)
|
||||||
|
@ -41,6 +41,7 @@ class NIO:
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._filters = {}
|
self._filters = {}
|
||||||
self._suspended = False
|
self._suspended = False
|
||||||
|
self._capturing = False
|
||||||
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
|
||||||
@ -115,6 +116,9 @@ class NIO:
|
|||||||
self._input_filter = filter_name
|
self._input_filter = filter_name
|
||||||
self._output_filter = filter_name
|
self._output_filter = filter_name
|
||||||
|
|
||||||
|
if filter_name == "capture":
|
||||||
|
self._capturing = True
|
||||||
|
|
||||||
async def unbind_filter(self, direction):
|
async def unbind_filter(self, direction):
|
||||||
"""
|
"""
|
||||||
Removes packet filter for this NIO.
|
Removes packet filter for this NIO.
|
||||||
@ -136,6 +140,7 @@ class NIO:
|
|||||||
elif direction == "both":
|
elif direction == "both":
|
||||||
self._input_filter = None
|
self._input_filter = None
|
||||||
self._output_filter = None
|
self._output_filter = None
|
||||||
|
self._capturing = False
|
||||||
|
|
||||||
async def setup_filter(self, direction, options):
|
async def setup_filter(self, direction, options):
|
||||||
"""
|
"""
|
||||||
@ -269,6 +274,15 @@ class NIO:
|
|||||||
assert isinstance(new_filters, dict)
|
assert isinstance(new_filters, dict)
|
||||||
self._filters = new_filters
|
self._filters = new_filters
|
||||||
|
|
||||||
|
@property
|
||||||
|
def capturing(self):
|
||||||
|
"""
|
||||||
|
Returns either a capture is configured on this NIO.
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._capturing
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""
|
||||||
NIO string representation.
|
NIO string representation.
|
||||||
|
@ -181,6 +181,7 @@ class ATMSwitch(Device):
|
|||||||
if port_number not in self._nios:
|
if port_number not in self._nios:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
# remove VCs mapped with the port
|
# remove VCs mapped with the port
|
||||||
for source, destination in self._active_mappings.copy().items():
|
for source, destination in self._active_mappings.copy().items():
|
||||||
if len(source) == 3 and len(destination) == 3:
|
if len(source) == 3 and len(destination) == 3:
|
||||||
@ -466,6 +467,8 @@ class ATMSwitch(Device):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
await nio.unbind_filter("both")
|
await nio.unbind_filter("both")
|
||||||
log.info('ATM switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
log.info('ATM switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -162,6 +162,7 @@ class EthernetHub(Bridge):
|
|||||||
if port_number not in self._mappings:
|
if port_number not in self._mappings:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
nio = self._mappings[port_number]
|
nio = self._mappings[port_number]
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
@ -226,6 +227,8 @@ class EthernetHub(Bridge):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
await nio.unbind_filter("both")
|
await nio.unbind_filter("both")
|
||||||
log.info('Ethernet hub "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
log.info('Ethernet hub "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -283,6 +283,7 @@ class EthernetSwitch(Device):
|
|||||||
if port_number not in self._nios:
|
if port_number not in self._nios:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
nio = self._nios[port_number]
|
nio = self._nios[port_number]
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
@ -455,6 +456,8 @@ class EthernetSwitch(Device):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
await nio.unbind_filter("both")
|
await nio.unbind_filter("both")
|
||||||
log.info('Ethernet switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
log.info('Ethernet switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -183,6 +183,7 @@ class FrameRelaySwitch(Device):
|
|||||||
if port_number not in self._nios:
|
if port_number not in self._nios:
|
||||||
raise DynamipsError("Port {} is not allocated".format(port_number))
|
raise DynamipsError("Port {} is not allocated".format(port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
# remove VCs mapped with the port
|
# remove VCs mapped with the port
|
||||||
for source, destination in self._active_mappings.copy().items():
|
for source, destination in self._active_mappings.copy().items():
|
||||||
source_port, source_dlci = source
|
source_port, source_dlci = source
|
||||||
@ -352,6 +353,8 @@ class FrameRelaySwitch(Device):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
await nio.unbind_filter("both")
|
await nio.unbind_filter("both")
|
||||||
log.info('Frame relay switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
log.info('Frame relay switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -1324,6 +1324,7 @@ class Router(BaseNode):
|
|||||||
raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter,
|
raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(slot_number, port_number)
|
||||||
await self.slot_disable_nio(slot_number, port_number)
|
await self.slot_disable_nio(slot_number, port_number)
|
||||||
await self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name,
|
await self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name,
|
||||||
slot_number=slot_number,
|
slot_number=slot_number,
|
||||||
@ -1477,6 +1478,8 @@ class Router(BaseNode):
|
|||||||
raise DynamipsError("Port {slot_number}/{port_number} is not connected".format(slot_number=slot_number,
|
raise DynamipsError("Port {slot_number}/{port_number} is not connected".format(slot_number=slot_number,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
await nio.unbind_filter("both")
|
await nio.unbind_filter("both")
|
||||||
|
|
||||||
log.info('Router "{name}" [{id}]: stopping packet capture on port {slot_number}/{port_number}'.format(name=self._name,
|
log.info('Router "{name}" [{id}]: stopping packet capture on port {slot_number}/{port_number}'.format(name=self._name,
|
||||||
|
@ -1315,6 +1315,8 @@ class IOUVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(adapter_number, port_number)
|
nio = self.get_nio(adapter_number, port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
log.info('IOU "{name}" [{id}]: stopping packet capture on {adapter_number}/{port_number}'.format(name=self._name,
|
log.info('IOU "{name}" [{id}]: stopping packet capture on {adapter_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -1275,6 +1275,7 @@ class QemuVM(BaseNode):
|
|||||||
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
|
await self.stop_capture(adapter_number)
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
await self._control_vm("set_link gns3-{} off".format(adapter_number))
|
await self._control_vm("set_link gns3-{} off".format(adapter_number))
|
||||||
await self._ubridge_send("bridge delete {name}".format(name="QEMU-{}-{}".format(self._id, adapter_number)))
|
await self._ubridge_send("bridge delete {name}".format(name="QEMU-{}-{}".format(self._id, adapter_number)))
|
||||||
@ -1342,6 +1343,8 @@ class QemuVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(adapter_number)
|
nio = self.get_nio(adapter_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
|
|
||||||
if self.ubridge:
|
if self.ubridge:
|
||||||
|
@ -348,6 +348,7 @@ class TraceNGVM(BaseNode):
|
|||||||
raise TraceNGError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter,
|
raise TraceNGError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
await self._ubridge_send("bridge delete {name}".format(name="TraceNG-{}".format(self._id)))
|
await self._ubridge_send("bridge delete {name}".format(name="TraceNG-{}".format(self._id)))
|
||||||
|
|
||||||
@ -409,6 +410,8 @@ class TraceNGVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
|
|
||||||
if self.ubridge:
|
if self.ubridge:
|
||||||
|
@ -1059,6 +1059,7 @@ class VirtualBoxVM(BaseNode):
|
|||||||
raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name,
|
raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
|
await self.stop_capture(adapter_number)
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
await self._ubridge_send("bridge delete {name}".format(name="VBOX-{}-{}".format(self._id, adapter_number)))
|
await self._ubridge_send("bridge delete {name}".format(name="VBOX-{}-{}".format(self._id, adapter_number)))
|
||||||
vm_state = await self._get_vm_state()
|
vm_state = await self._get_vm_state()
|
||||||
@ -1134,6 +1135,8 @@ class VirtualBoxVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(adapter_number)
|
nio = self.get_nio(adapter_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
|
|
||||||
if self.ubridge:
|
if self.ubridge:
|
||||||
|
@ -779,6 +779,7 @@ class VMwareVM(BaseNode):
|
|||||||
raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name,
|
raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
|
await self.stop_capture(adapter_number)
|
||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
@ -916,6 +917,8 @@ class VMwareVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(adapter_number)
|
nio = self.get_nio(adapter_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
|
|
||||||
if self._started:
|
if self._started:
|
||||||
|
@ -405,6 +405,7 @@ class VPCSVM(BaseNode):
|
|||||||
raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter,
|
raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
|
await self.stop_capture(port_number)
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
await self._ubridge_send("bridge delete {name}".format(name="VPCS-{}".format(self._id)))
|
await self._ubridge_send("bridge delete {name}".format(name="VPCS-{}".format(self._id)))
|
||||||
|
|
||||||
@ -466,6 +467,8 @@ class VPCSVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
nio = self.get_nio(port_number)
|
nio = self.get_nio(port_number)
|
||||||
|
if not nio.capturing:
|
||||||
|
return
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
|
|
||||||
if self.ubridge:
|
if self.ubridge:
|
||||||
|
@ -390,6 +390,17 @@ class Link:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def capture_compute_id(self):
|
||||||
|
"""
|
||||||
|
Get the capture compute ID.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._capture_node:
|
||||||
|
return self.capture_node["node"].compute.id
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def available_filters(self):
|
def available_filters(self):
|
||||||
"""
|
"""
|
||||||
Return the list of filters compatible with this link
|
Return the list of filters compatible with this link
|
||||||
@ -455,6 +466,7 @@ class Link:
|
|||||||
"capturing": self._capturing,
|
"capturing": self._capturing,
|
||||||
"capture_file_name": self._capture_file_name,
|
"capture_file_name": self._capture_file_name,
|
||||||
"capture_file_path": self.capture_file_path,
|
"capture_file_path": self.capture_file_path,
|
||||||
|
"capture_compute_id": self.capture_compute_id,
|
||||||
"link_type": self._link_type,
|
"link_type": self._link_type,
|
||||||
"filters": self._filters,
|
"filters": self._filters,
|
||||||
"suspend": self._suspended
|
"suspend": self._suspended
|
||||||
|
@ -74,11 +74,15 @@ LINK_OBJECT_SCHEMA = {
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"capture_file_name": {
|
"capture_file_name": {
|
||||||
"description": "Read only property. The name of the capture file if capture is running",
|
"description": "Read only property. The name of the capture file if a capture is running",
|
||||||
"type": ["string", "null"]
|
"type": ["string", "null"]
|
||||||
},
|
},
|
||||||
"capture_file_path": {
|
"capture_file_path": {
|
||||||
"description": "Read only property. The full path of the capture file if capture is running",
|
"description": "Read only property. The full path of the capture file if a capture is running",
|
||||||
|
"type": ["string", "null"]
|
||||||
|
},
|
||||||
|
"capture_compute_id": {
|
||||||
|
"description": "Read only property. The compute identifier where a capture is running",
|
||||||
"type": ["string", "null"]
|
"type": ["string", "null"]
|
||||||
},
|
},
|
||||||
"link_type": {
|
"link_type": {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
# or negative for a release candidate or beta (after the base version
|
# or negative for a release candidate or beta (after the base version
|
||||||
# number has been incremented)
|
# number has been incremented)
|
||||||
|
|
||||||
__version__ = "2.2.0dev8"
|
__version__ = "2.2.0dev9"
|
||||||
__version_info__ = (2, 2, 0, 99)
|
__version_info__ = (2, 2, 0, 99)
|
||||||
|
|
||||||
# If it's a git checkout try to add the commit
|
# If it's a git checkout try to add the commit
|
||||||
|
@ -235,7 +235,8 @@ def test_json(async_run, project, compute, link):
|
|||||||
"link_type": "ethernet",
|
"link_type": "ethernet",
|
||||||
"capturing": False,
|
"capturing": False,
|
||||||
"capture_file_name": None,
|
"capture_file_name": None,
|
||||||
"capture_file_path": None
|
"capture_file_path": None,
|
||||||
|
"capture_compute_id": None
|
||||||
}
|
}
|
||||||
assert link.__json__(topology_dump=True) == {
|
assert link.__json__(topology_dump=True) == {
|
||||||
"link_id": link.id,
|
"link_id": link.id,
|
||||||
|
Loading…
Reference in New Issue
Block a user