mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 11:18:11 +00:00
parent
d0f65aebff
commit
46b6e7c5ee
@ -348,7 +348,7 @@ class DockerVM(BaseNode):
|
||||
yield from self._clean_servers()
|
||||
|
||||
yield from self.manager.query("POST", "containers/{}/start".format(self._cid))
|
||||
namespace = yield from self._get_namespace()
|
||||
self._namespace = yield from self._get_namespace()
|
||||
|
||||
yield from self._start_ubridge()
|
||||
|
||||
@ -356,7 +356,7 @@ class DockerVM(BaseNode):
|
||||
nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
||||
with (yield from self.manager.ubridge_lock):
|
||||
try:
|
||||
yield from self._add_ubridge_connection(nio, adapter_number, namespace)
|
||||
yield from self._add_ubridge_connection(nio, adapter_number)
|
||||
except UbridgeNamespaceError:
|
||||
yield from self.stop()
|
||||
|
||||
@ -626,13 +626,12 @@ class DockerVM(BaseNode):
|
||||
return
|
||||
|
||||
@asyncio.coroutine
|
||||
def _add_ubridge_connection(self, nio, adapter_number, namespace):
|
||||
def _add_ubridge_connection(self, nio, adapter_number):
|
||||
"""
|
||||
Creates a connection in uBridge.
|
||||
|
||||
:param nio: NIO instance or None if it's a dummy interface (if an interface is missing in ubridge you can't see it via ifconfig in the container)
|
||||
:param adapter_number: adapter number
|
||||
:param namespace: Container namespace (pid)
|
||||
"""
|
||||
|
||||
try:
|
||||
@ -652,45 +651,34 @@ class DockerVM(BaseNode):
|
||||
yield from self._ubridge_send('bridge create bridge{}'.format(adapter_number))
|
||||
yield from self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number,
|
||||
hostif=adapter.host_ifc))
|
||||
log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.host_ifc, namespace)
|
||||
log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.host_ifc, self._namespace)
|
||||
try:
|
||||
yield from self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.host_ifc,
|
||||
ns=namespace,
|
||||
ns=self._namespace,
|
||||
adapter=adapter_number))
|
||||
except UbridgeError as e:
|
||||
raise UbridgeNamespaceError(e)
|
||||
|
||||
if isinstance(nio, NIOUDP):
|
||||
yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
|
||||
lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport))
|
||||
|
||||
if nio and nio.capturing:
|
||||
yield from self._ubridge_send('bridge start_capture bridge{adapter} "{pcap_file}"'.format(adapter=adapter_number,
|
||||
pcap_file=nio.pcap_output_file))
|
||||
|
||||
if nio:
|
||||
yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number))
|
||||
|
||||
def _delete_ubridge_connection(self, adapter_number):
|
||||
"""Deletes a connection in uBridge.
|
||||
|
||||
:param adapter_number: adapter number
|
||||
"""
|
||||
if not self.ubridge:
|
||||
return
|
||||
|
||||
try:
|
||||
yield from self._ubridge_send("bridge delete bridge{name}".format(name=adapter_number))
|
||||
except UbridgeError as e:
|
||||
log.debug(str(e))
|
||||
yield from self._connect_nio(adapter_number, nio)
|
||||
|
||||
@asyncio.coroutine
|
||||
def _get_namespace(self):
|
||||
result = yield from self.manager.query("GET", "containers/{}/json".format(self._cid))
|
||||
return int(result['State']['Pid'])
|
||||
|
||||
@asyncio.coroutine
|
||||
def _connect_nio(self, adapter_number, nio):
|
||||
yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
|
||||
lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport))
|
||||
|
||||
if nio.capturing:
|
||||
yield from self._ubridge_send('bridge start_capture bridge{adapter} "{pcap_file}"'.format(adapter=adapter_number,
|
||||
pcap_file=nio.pcap_output_file))
|
||||
yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number))
|
||||
|
||||
@asyncio.coroutine
|
||||
def adapter_add_nio_binding(self, adapter_number, nio):
|
||||
"""Adds an adapter NIO binding.
|
||||
@ -705,28 +693,7 @@ class DockerVM(BaseNode):
|
||||
adapter_number=adapter_number))
|
||||
|
||||
if self.status == "started" and self.ubridge:
|
||||
# the container is running, let's add the UDP tunnel to connect to another node
|
||||
yield from self._ubridge_send('bridge create bridge{}'.format(adapter_number))
|
||||
yield from self._ubridge_send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number))
|
||||
|
||||
yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
|
||||
lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport))
|
||||
|
||||
yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number))
|
||||
|
||||
if self.status == "started" and self.ubridge:
|
||||
# the container is running, let's add the UDP tunnel to connect to another node
|
||||
yield from self._ubridge_hypervisor.send('bridge create bridge{}'.format(adapter_number))
|
||||
yield from self._ubridge_hypervisor.send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number))
|
||||
|
||||
yield from self._ubridge_hypervisor.send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
|
||||
lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport))
|
||||
|
||||
yield from self._ubridge_hypervisor.send('bridge start bridge{adapter}'.format(adapter=adapter_number))
|
||||
yield from self._connect_nio(adapter_number, nio)
|
||||
|
||||
adapter.add_nio(0, nio)
|
||||
log.info("Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name,
|
||||
@ -749,13 +716,15 @@ class DockerVM(BaseNode):
|
||||
raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name,
|
||||
adapter_number=adapter_number))
|
||||
|
||||
if self.ubridge:
|
||||
nio = adapter.get_nio(0)
|
||||
yield from self._ubridge_send("bridge stop bridge{name}".format(name=adapter_number))
|
||||
yield from self._ubridge_send('bridge remove_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
|
||||
lport=nio.lport,
|
||||
rhost=nio.rhost,
|
||||
rport=nio.rport))
|
||||
|
||||
adapter.remove_nio(0)
|
||||
if self.status == "started" and self.ubridge:
|
||||
# the container is running, just delete the UDP tunnel so we can reconnect it later if needed
|
||||
yield from self._ubridge_send("bridge delete bridge{name}".format(name=adapter_number))
|
||||
else:
|
||||
# the container is not running, let's completely delete the connection
|
||||
yield from self._delete_ubridge_connection(adapter_number)
|
||||
|
||||
log.info("Docker VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name,
|
||||
id=self.id,
|
||||
|
@ -419,7 +419,7 @@ def test_start(loop, vm, manager, free_console_port):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
|
||||
mock_query.assert_called_with("POST", "containers/e90e34656842/start")
|
||||
vm._add_ubridge_connection.assert_called_once_with(nio, 0, 42)
|
||||
vm._add_ubridge_connection.assert_called_once_with(nio, 0)
|
||||
assert vm._start_ubridge.called
|
||||
assert vm._start_console.called
|
||||
assert vm._start_aux.called
|
||||
@ -445,7 +445,7 @@ def test_start_namespace_failed(loop, vm, manager, free_console_port):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
|
||||
mock_query.assert_any_call("POST", "containers/e90e34656842/start")
|
||||
mock_add_ubridge_connection.assert_called_once_with(nio, 0, 42)
|
||||
mock_add_ubridge_connection.assert_called_once_with(nio, 0)
|
||||
assert mock_start_ubridge.called
|
||||
assert vm.status == "stopped"
|
||||
|
||||
@ -691,8 +691,9 @@ def test_add_ubridge_connection(loop, vm):
|
||||
nio = vm.manager.create_nio(nio)
|
||||
nio.startPacketCapture("/tmp/capture.pcap")
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._namespace = 42
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42)))
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
calls = [
|
||||
call.send('bridge create bridge0'),
|
||||
@ -710,8 +711,9 @@ def test_add_ubridge_connection_none_nio(loop, vm):
|
||||
|
||||
nio = None
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._namespace = 42
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42)))
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
calls = [
|
||||
call.send('bridge create bridge0'),
|
||||
@ -731,7 +733,7 @@ def test_add_ubridge_connection_invalid_adapter_number(loop, vm):
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 12, 42)))
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 12)))
|
||||
|
||||
|
||||
def test_add_ubridge_connection_no_free_interface(loop, vm):
|
||||
@ -747,25 +749,7 @@ def test_add_ubridge_connection_no_free_interface(loop, vm):
|
||||
interfaces = ["tap-gns3-e{}".format(index) for index in range(4096)]
|
||||
|
||||
with patch("psutil.net_if_addrs", return_value=interfaces):
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42)))
|
||||
|
||||
|
||||
def test_delete_ubridge_connection(loop, vm):
|
||||
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
nio = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42)))
|
||||
loop.run_until_complete(asyncio.async(vm._delete_ubridge_connection(0)))
|
||||
|
||||
calls = [
|
||||
call.send("bridge delete bridge0"),
|
||||
]
|
||||
vm._ubridge_hypervisor.assert_has_calls(calls, any_order=True)
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
|
||||
def test_adapter_add_nio_binding(vm, loop):
|
||||
@ -789,16 +773,21 @@ def test_adapter_add_nio_binding_invalid_adapter(vm, loop):
|
||||
|
||||
|
||||
def test_adapter_remove_nio_binding(vm, loop):
|
||||
vm.ubridge = MagicMock()
|
||||
vm.ubridge.is_running.return_value = True
|
||||
|
||||
nio = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._delete_ubridge_connection") as delete_ubridge_mock:
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._ubridge_send") as delete_ubridge_mock:
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_remove_nio_binding(0)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0) is None
|
||||
delete_ubridge_mock.assert_called_with(0)
|
||||
delete_ubridge_mock.assert_any_call('bridge stop bridge0')
|
||||
delete_ubridge_mock.assert_any_call('bridge remove_nio_udp bridge0 4242 127.0.0.1 4343')
|
||||
|
||||
|
||||
def test_adapter_remove_nio_binding_invalid_adapter(vm, loop):
|
||||
|
Loading…
Reference in New Issue
Block a user