mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
parent
d0f65aebff
commit
46b6e7c5ee
@ -348,7 +348,7 @@ class DockerVM(BaseNode):
|
|||||||
yield from self._clean_servers()
|
yield from self._clean_servers()
|
||||||
|
|
||||||
yield from self.manager.query("POST", "containers/{}/start".format(self._cid))
|
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()
|
yield from self._start_ubridge()
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ class DockerVM(BaseNode):
|
|||||||
nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
||||||
with (yield from self.manager.ubridge_lock):
|
with (yield from self.manager.ubridge_lock):
|
||||||
try:
|
try:
|
||||||
yield from self._add_ubridge_connection(nio, adapter_number, namespace)
|
yield from self._add_ubridge_connection(nio, adapter_number)
|
||||||
except UbridgeNamespaceError:
|
except UbridgeNamespaceError:
|
||||||
yield from self.stop()
|
yield from self.stop()
|
||||||
|
|
||||||
@ -626,13 +626,12 @@ class DockerVM(BaseNode):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _add_ubridge_connection(self, nio, adapter_number, namespace):
|
def _add_ubridge_connection(self, nio, adapter_number):
|
||||||
"""
|
"""
|
||||||
Creates a connection in uBridge.
|
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 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 adapter_number: adapter number
|
||||||
:param namespace: Container namespace (pid)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
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 create bridge{}'.format(adapter_number))
|
||||||
yield from self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number,
|
yield from self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number,
|
||||||
hostif=adapter.host_ifc))
|
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:
|
try:
|
||||||
yield from self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.host_ifc,
|
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))
|
adapter=adapter_number))
|
||||||
except UbridgeError as e:
|
except UbridgeError as e:
|
||||||
raise UbridgeNamespaceError(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:
|
if nio:
|
||||||
yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number))
|
yield from self._connect_nio(adapter_number, nio)
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _get_namespace(self):
|
def _get_namespace(self):
|
||||||
result = yield from self.manager.query("GET", "containers/{}/json".format(self._cid))
|
result = yield from self.manager.query("GET", "containers/{}/json".format(self._cid))
|
||||||
return int(result['State']['Pid'])
|
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
|
@asyncio.coroutine
|
||||||
def adapter_add_nio_binding(self, adapter_number, nio):
|
def adapter_add_nio_binding(self, adapter_number, nio):
|
||||||
"""Adds an adapter NIO binding.
|
"""Adds an adapter NIO binding.
|
||||||
@ -705,28 +693,7 @@ class DockerVM(BaseNode):
|
|||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if self.status == "started" and self.ubridge:
|
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._connect_nio(adapter_number, nio)
|
||||||
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))
|
|
||||||
|
|
||||||
adapter.add_nio(0, nio)
|
adapter.add_nio(0, nio)
|
||||||
log.info("Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name,
|
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,
|
raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name,
|
||||||
adapter_number=adapter_number))
|
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)
|
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,
|
log.info("Docker VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name,
|
||||||
id=self.id,
|
id=self.id,
|
||||||
|
@ -419,7 +419,7 @@ def test_start(loop, vm, manager, free_console_port):
|
|||||||
loop.run_until_complete(asyncio.async(vm.start()))
|
loop.run_until_complete(asyncio.async(vm.start()))
|
||||||
|
|
||||||
mock_query.assert_called_with("POST", "containers/e90e34656842/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_ubridge.called
|
||||||
assert vm._start_console.called
|
assert vm._start_console.called
|
||||||
assert vm._start_aux.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()))
|
loop.run_until_complete(asyncio.async(vm.start()))
|
||||||
|
|
||||||
mock_query.assert_any_call("POST", "containers/e90e34656842/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 mock_start_ubridge.called
|
||||||
assert vm.status == "stopped"
|
assert vm.status == "stopped"
|
||||||
|
|
||||||
@ -691,8 +691,9 @@ def test_add_ubridge_connection(loop, vm):
|
|||||||
nio = vm.manager.create_nio(nio)
|
nio = vm.manager.create_nio(nio)
|
||||||
nio.startPacketCapture("/tmp/capture.pcap")
|
nio.startPacketCapture("/tmp/capture.pcap")
|
||||||
vm._ubridge_hypervisor = MagicMock()
|
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 = [
|
calls = [
|
||||||
call.send('bridge create bridge0'),
|
call.send('bridge create bridge0'),
|
||||||
@ -710,8 +711,9 @@ def test_add_ubridge_connection_none_nio(loop, vm):
|
|||||||
|
|
||||||
nio = None
|
nio = None
|
||||||
vm._ubridge_hypervisor = MagicMock()
|
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 = [
|
calls = [
|
||||||
call.send('bridge create bridge0'),
|
call.send('bridge create bridge0'),
|
||||||
@ -731,7 +733,7 @@ def test_add_ubridge_connection_invalid_adapter_number(loop, vm):
|
|||||||
"rhost": "127.0.0.1"}
|
"rhost": "127.0.0.1"}
|
||||||
nio = vm.manager.create_nio(nio)
|
nio = vm.manager.create_nio(nio)
|
||||||
with pytest.raises(DockerError):
|
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):
|
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)]
|
interfaces = ["tap-gns3-e{}".format(index) for index in range(4096)]
|
||||||
|
|
||||||
with patch("psutil.net_if_addrs", return_value=interfaces):
|
with patch("psutil.net_if_addrs", return_value=interfaces):
|
||||||
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)))
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
def test_adapter_add_nio_binding(vm, loop):
|
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):
|
def test_adapter_remove_nio_binding(vm, loop):
|
||||||
|
vm.ubridge = MagicMock()
|
||||||
|
vm.ubridge.is_running.return_value = True
|
||||||
|
|
||||||
nio = {"type": "nio_udp",
|
nio = {"type": "nio_udp",
|
||||||
"lport": 4242,
|
"lport": 4242,
|
||||||
"rport": 4343,
|
"rport": 4343,
|
||||||
"rhost": "127.0.0.1"}
|
"rhost": "127.0.0.1"}
|
||||||
nio = vm.manager.create_nio(nio)
|
nio = vm.manager.create_nio(nio)
|
||||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, 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)))
|
loop.run_until_complete(asyncio.async(vm.adapter_remove_nio_binding(0)))
|
||||||
assert vm._ethernet_adapters[0].get_nio(0) is None
|
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):
|
def test_adapter_remove_nio_binding_invalid_adapter(vm, loop):
|
||||||
|
Loading…
Reference in New Issue
Block a user